Overview
Let's first look at the general architecture diagram of spring
basic interface
Resource+ResourceLoader
The configuration files we write in the form of xml or annotations are all Resource
resources in spring, and spring also provides one ResourceLoader
to load the resources we write
BeanFactory
Let's first take a look at the inheritance relationship of beanfactory. The interface of beanFactory defines some basic methods for obtaining beans, nothing special. Next look at the three interfaces below the bean
- HierarchicalBeanFactory
Just define the parent-child relationship of beanFactory 2. The interface defined in the official documentation of ListableBeanFactory is designed to allow people to traverse the beans in the container better, so we can also see that the newly added interface returns an array of bean names
DefaultListableBeanFactory
After looking at the sub-interface of BeanFactory above, let's look at an implementation class. Let's first look at the GenericApplicationContext
class . This class is the parent class of our commonly used IOC container. We can see that there is a member variable in this class.DefaultListableBeanFactory
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
bean的名称映射
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
根据类型和名称的映射
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
只有单利的类和名称映射
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
获得所有bean信息
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
复制代码
This class is from spring 信息中心,包含所有bean的定义信息
, but the ioc container he uses with us is not an inheritance relationship but a combination relationship
BeanDefinition
BeanDefinition describes an instance of a bean, which can obtain properties such as the bean name, scope, whether it is lazy loaded, and so on.
BeanDefinitionRegistry
A BeanDefinition registry, which contains the mapping relationship of BeanDefinition
ApplicationContext
包含了很多功能,从继承接口可以看出,包含了ioc事件派发器,国际化解析,bean工厂,资源解析功能
Aware
在spring中有非常多的XXXAware,用了之后就可以获得到对象实例
BeanDefinition信息注册到BeanDefinitionRegistry流程
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Cat bean = context.getBean(Cat.class);
System.out.println(bean);
}
复制代码
代码很简单,现在来debug看spring注册流程
- 在
ClassPathXmlApplicationContext
的构造方法里执行了refresh方法
2. refresh是 AbstractApplicationContext
的方法,又调用了obtainFreshBeanFactory
让子类刷新内部的beanFactory 3. 随后调用了 AbstractRefreshableApplicationContext
类的 refreshBeanFactory方法。我们可以看到在这里创建了一个 DefaultListableBeanFactory
,然后把该对象传入子类的loadBeanDefinition
方法 4. 来到AbstractXmlApplicationContext
类的loadBeanDefinition,根据DefaultListableBeanFactory创建了一个XMLBeanDefinitionReader
然后读取配置文件 5. XMLBeanDefinitionReader
的doLoadBeanDefinition方法中,根据配置文件生成Document对象然后读取 随后再创建了一个 BeanDefinitionDocumentDocumentReader
,调用registerBeanDefinitions方法读取数据 6. 在BeanDefinitionDocumentDocumentReader 的内部有一个代理类,解析数据其实都是该类实现的 方法内遍历每一个节点解析数据 然后解析内部就是判断xml标签走不同的方法 7. 在解析bean的方法内部先封装了一个 BeanDefinitionHolder
组合了bean的名称和BeanDefinition
,然后调用一个工具类解析数据 8. 工具类内部调用 DefaultListableBeanFactory
的 方法注册Bean信息到档案馆 9. 现在正式来到DefaultListableBeanFactory
内部,首先会判断这个beanName是否已经在BeanDefinitionMap中存在,如果不存在就添加到map里面,并且也会添加一个名字列表到数组中
创建单实例Bean流程
我们刚才看的是Bean的定义信息已经被保存到spring中,我们现在来看看Spring创建实体对象的流程。
- 还是
AbstractApplicationContext
类的refresh方法,方法走到了finishBeanFactoryInitialization
方法,该方法主要设置了一些beanFactory的一些参数然后调用preInstanceSingletons
方法
2. 这个beanFactory就是那个DefaultListableBeanFactory
,方法中通过遍历之前已经初始化好的BeanDefinitionNames,创建不是抽象,是单例,不是懒加载的对象 3. 方法来到了父类AbstractBeanFactory
中的doGetBean
方法中,这个方法有很多逻辑,我们先来看首次创建的逻辑 4. 做了上面一系列判断之后,调用父类DefaultSingletonBeanRegistry
的getSingleton方法,方法中还会有一个回调,先不看父类的方法逻辑,直接看回调方法的createBean
,这是一个抽象方法,由子类AbstractAutowireCapableBeanFactory
实现 5. 执行一些暂时无意义的方法之后来到了instantiateBean
方法,内部有一个创建bean的策略类,实现有jdk的反射和cglib 6. spring在创建bean的过程中会判断该对象是否有重写的方法,如果有的话就走gclib,没有就走jdk默认
Bean属性赋值过程
我们上面看完了Bean实例的创建过程再来看一下Bean内部的属性是如何被spring注入进来的。在AbstractAutowireCapableBeanFactory
的doCreateBean方法中创建完bean实例之后继续往下执行
- 在doCreateBean方法内部,实例化bean后调用
populateBean
方法给bean属性赋值
2. 在populateBean方法中,如果是注解的方式启动的spring则会走后置处理器的方式来赋值对象,如果是xml的形式则会走另一个方法,现在大部分都是注解的方式启动的容器,所以我们直接看后置处理器的方式 3. 在初始化完bean之后spring会执行容器中的所有InstantiationAwareBeanPostProcessor
对象的postProcessProperties方法,在方法中获得一个InjectionMetadata
对象,该对象就有需要注入的对象和方法,后面就是直接调用invoke方法就可以了。 4. 我们再来看看spring是如何寻找@Autowire
注解的,在上面方法的第一行的方法findAutowiringMetadata
进去 可以看到其实返回的数据是调用buildAutowiringMetadata
方法 该方法是从目标类一直循环上去,找属性是不是有目标注解 遍历集合判断是否有数据 数据的初始化就是添加这些注解
spring的后置处理器
spring提供了三种后置处理器
BeanFactoryPostProcessor
BeanPostProcessor
InitializingBean
我们来依次看每个后置处理器的执行流程。
BeanFactoryPostProcessor
首先还是回到refresh方法中,我们可以看到在创建普通bean对象的上面有个方法叫invokeBeanFactoryPostProcessor,从方法名就可以看出是执行BeanFactoryPostProcessor方法 方法内部调用了一个代理类的静态方法 方法内部会首先拿出实现了PriorityOrdered
接口的对象排序后执行
执行完PriorityOrdered
接口后再拿出实现了Order
接口的对象执行 最后把剩下的BeanFactoryPostProcessor根据类名排序后调用方法,这时候容器里面还是没有对象的,在getBean的时候需要走原来看过的创建普通bean的流程 前面的都是执行的BeanDefinitionRegistryPostProcessor
的方法postProcessBeanDefinitionRegistry
,三个判断结束之后最后执行BeanFactoryPostProcessor
的postProcessBeanFactory
方法 流程图如下
工厂后置增强的实际用途
我们现在知道了spring提供了一些工厂的后置处理器来增强工厂,那么我们现在来看看spring中实际使用工厂后置处理器做了什么事情,我们来看一个类ConfigurationClassPostProcessor
这个类是用于处理写了@Configuratioin
注解的类 排序好之后就在一个循环里面解析容器里面的类 在方法中先判断是不是需要跳过,如果写了@Conditional
注解的对象会判断条件是否生效 真正解析配置类的方法里面就是各种判断注解的情况,然后去做相应的方法
BeanPostProcessor 注册
工厂的增强至此就结束了,接下来看看普通组件的后置处理器的逻辑,还是回到refresh方法,这次是调用registerBeanPostProcessors
方法,注册后置处理器。 注册的逻辑跟BeanFactory都是由同一个代理类来完成的 大部分逻辑和bean工厂的逻辑一致,都是判断优先级接口的就先执行 跟bean工厂不一致的是,bean工厂的后置处理器直接执行目标方法,这里只是把bean后置处理器创建好之后就放入list中
InstantiationAwareBeanPostProcessor
所有的BeanPostProcessor都被注册之后,我们来看其中一个分支:InstantiationAwareBeanPostProcessor
的流程
SmartInstantiationAwareBeanPostProcessor
从名字上可以看出叫智能的
实例后置处理器,那么这个我们就来看看智能在什么地方. 在refresh方法中调用了一个注册监听器的方法 在该方法中调用了一个根据类型获取名称列表
的方法,该方法是ListableBeanFactory
接口的一个方法 为了获得目标类的名称,spring遍历所有的bean的名称,一个一个判断
判断逻辑是先判断已经初始化好的实例,然后再判断bean定义信息,如果都没有则让别人来判断 拿到容器中的SmartInstantiationAwareBeanPostProcessor然后把类名和bean名称穿进去,让实现类来决定 总结流程图 所以我们知道,在spring中,根据类型来找名称其实spring需要遍历所有对象,是一件很麻烦的事情
InstantiationAwareBeanPostProcessor
在spring容器创建对象之前,会先调用 InstantiationAwareBeanPostProcessor的 postProcessBeforeInstantiation
方法尝试返回对象,如果用户返回了则会用用户创建的对象。 如果没有则调用doCreateBean方法,方法内也会从一个缓存中获取,没有的话就继续调用方法创建 创建逻辑会让用户返回一个构造函数,注意这里调用的是SmartInstantiationAwareBeanPostProcessor的一个方法,如果没有就用默认的无参构造函数,之后就是上面写过的用工具类创建的方式
MergedBeanDefinitionPostProcessor
在创建好bean实例对象之后会调用一下MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法让用户定义一下BeanDefinition
PopulateBean
之后就进入属性赋值方法,首先会先执行 InstantiationAwareBeanPostProcessor
的 postProcessAfterInstantiation方法,返回bool类型的值,如果返回true则会继续属性赋值,返回false则不会属性赋值 如果返回true则开始执行InstantiationAwareBeanPostProcessor
的 postProcessProperties方法。自动注入 AutowiredAnnotationBeanPostProcessor
的该方法就实现了自动注入的属性赋值
PropertyValues
在上面我们可以看到postProcessProperties方法返回了一个pvs,我们也可以自定义返回pvs,spring最后会帮我们注入到对象中,创建一个PVS返回即可
BeanPostProcessor
属性赋值之后spring会执行initializeBean
方法初始化bean,首先会先执行一些 Aware
的注入
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
The initialization process is as follows postProcessBeforeInitialization
: The method is executed before the initialization method is called, so that the user can 不断的包装对象
, if one returns null, then the loop is ended. After the object is returned , the initialization method is executed. InitializingBean
The method is triggered here. After the initialization method is executed postProcessBeforeInitialization
, spring will call Another lifecycle method that also allows users to wrap several layers