文章目录
- 1、Spring架构概述
- 2、BeanFactory接口
- 3、BeanDefinition
- 4、BeanDefinitionReader
- 5、BeanDefinitionRegistry
- 6、创建容器
1、Spring架构概述
Spring包含约20个模块,1300多个文件。主要架构:
Spring面向Bean编程,Bean即受Spring容器管控的对象,而核心容器则是由beans、core、context、express(Spring Expression Language,SpEL)4个模块组成。
1)spring-beans 和 spring-core是核心,包含了控制反转IoC和依赖注入DI。核心接口BeanFactory。
BeanFactory属于延时加载,也就是说在实例化容器对象后并不会自动实例化Bean,只有当Bean被使用时,BeanFactory才会对该 Bean 进行实例化与依赖关系的装配。
2)spring-context模块,扩展了BeanFactory,其核心接口ApplicationContext就是BeanFactory的子接口。该模块添加了Bean的生命周期控制等
与BeanFactory不同,ApplicationContext实例化后会自动对所有的单实例Bean进行实例化与依赖关系的装配,使之处于待用状态。
最后,关于上面BeanFactory延时加载,而ApplicationContext非延时加载的Demo。先准备个测试Bean:
<bean id="userService" class="com.plat.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.plat.dao.impl.UserDaoImpl"></bean>
改下类的无参构造,让它在被调用时打印一句话,以便下面观察Bean何时被实例化的:
@Setter
public class UserServiceImpl implements UserService {private UserDao ueserDao; //声明个UserDao类型的对象public UserServiceImpl(){System.out.println("userService被创建了");}
}
public class UserDaoImpl implements UserDao {public UserDaoImpl(){System.out.println("UserDao被创建了");}
}
打断点:
//创建Spring容器对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicaitonContext.xml");
//从容器中获取Bean
UserService bean = applicationContext.getBean("userService", UserService.class);
同样的断点:
//创建Spring容器对象
BeanFactory beanFacotry = new XmlBeanFactory(new ClassPathResource("applicaitonContext.xml"));
//从容器中获取Bean
UserService bean = beanFacotry.getBean("userService", UserService.class);
2、BeanFactory接口
Spring中Bean的创建是工厂模式的应用,确切的说是简单工厂 + 配置文件的形式。
这一系列的Bean工厂,即IoC容器,帮助开发者创建和管理对象及对象间的依赖关系。BeanFactory作为最顶层的一个接口,定义了IoC容器的基本功能规范。
BeanFactory的源码:
public interface BeanFactory {String FACTORY_BEAN_PREFIX = "&";//根据bean的名称获取IOC容器中的的bean对象Object getBean(String name) throws BeansException;//根据bean的名称获取IOC容器中的的bean对象,并指定获取到的bean对象的类型,这样我们使用时就不需要进行类型强转了<T> T getBean(String name, Class<T> requiredType) throws BeansException;Object getBean(String name, Object... args) throws BeansException;<T> T getBean(Class<T> requiredType) throws BeansException;<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);//判断容器中是否包含指定名称的bean对象boolean containsBean(String name);//根据bean的名称判断是否是单例boolean isSingleton(String name) throws NoSuchBeanDefinitionException;boolean isPrototype(String name) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;@NullableClass<?> getType(String name) throws NoSuchBeanDefinitionException;String[] getAliases(String name);
}
BeanFactory接口有个重要的子接口ApplicationContext,它规范了其子类IoC容器中的bean对象是非延时加载,即在创建容器对象的时候就对象bean进行初始化,并存储到一个容器中。
如上,不同的子类,即不同的IoC容器,它们生产对象的方式也是不同的:
ClasspathXmlApplicationContext
: 根据类路径加载xml配置文件,并创建IOC容器对象。FileSystemXmlApplicationContext
:根据系统路径加载xml配置文件,并创建IOC容器对象。AnnotationConfigApplicationContext
:加载注解类配置,并创建IOC容器。
3、BeanDefinition
开发者在xml中描述自己的Bean,而定义的Bean的那些属性,在Spring中用BeanDefinition来描述。
BeanDefinition对xml中的Bean相关的属性进行封装,那这个xml配置文件由谁解析呢 ⇒ BeanDefinitionReader
4、BeanDefinitionReader
Bean的解析主要就是对Spring配置文件的解析。这个解析过程主要通过BeanDefinitionReader来完成。
BeanDefinitionReader接口定义了解析的规范,其不同的子实现类,则用于解析不同的配置文件,如xml、Properties
public interface BeanDefinitionReader {//获取BeanDefinitionRegistry注册器对象BeanDefinitionRegistry getRegistry();/*下面的loadBeanDefinitions都是加载bean定义,从指定的资源中*/int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}
5、BeanDefinitionRegistry
BeanDefinitionReader用来解析bean的定义,然后封装到BeanDefinition对象。而封装的BeanDefinition对象,则存储到了BeanDefinition的注册中心,该注册中心的顶层接口就是BeanDefinitionRegistry
public interface BeanDefinitionRegistry extends AliasRegistry {//往注册表中注册beanvoid registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException;//从注册表中删除指定名称的beanvoid removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;//获取注册表中指定名称的beanBeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;//判断注册表中是否已经注册了指定名称的beanboolean containsBeanDefinition(String beanName);//获取注册表中所有的bean的名称,返回一个数组String[] getBeanDefinitionNames();//获取注册表中BeanDefiniton的数量int getBeanDefinitionCount();//判断bean的名字在注册表中是否已被使用boolean isBeanNameInUse(String beanName);
}
Ctrl+H看继承体系:
看其子类的源码,里面定义了Map,key为String,value为BeanDefinition。
6、创建容器
以ClassPathXmlApplicationContext这个Ioc类为例,创建它的对象(IoC容器对象)是传入了xml的文件名,找到源码中的相关构造方法,this调用了另一个构造方法,继续跟进:
看到调用了refresh方法:
跟进refresh方法,发现到了父类的refresh方法。refresh方法是一个模板方法,该方法定义好了 IoC 容器的启动流程(加载配置文件、初始化Bean对象、将Bean对象存储到容器中等等),有些逻辑要交给其子类实现。它对 Bean 配置资源进行载入,ClassPathXmlApplicationContext通过调用其父类AbstractApplicationContext的refresh方法启动整个IoC容器对Bean定义的载入过程。