天天看点

Spring系列(三) 从refresh看createBean源码解析

createBean解析

spring当中单例bean的创建原理,其中涉及到了非常多阶段及各种处理器的调用

启动代码

通过注解配置类AppConfig启动一个容器,其中添加了一个自定义的beanFactoryPostProcessor, 注意:这个类是直接添加到beanFactoryPostProcessors中的,没有被spring当成bean放到单例map中

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
        ac.addBeanFactoryPostProcessor(new CustomBeanFactoryPostProcessor());
        ac.register(AppConfig.class);
        ac.refresh();
           

new AnnotationConfigApplicationContext

完成的初始化:

this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
           

初始化了AnnotatedBeanDefinitionReader又完成了spring内置几大处理器的注册

生成了对应RootBeanDefinition,并通过registry加到了map中

beanName beanClass
org.springframework.context.annotation.internalConfigurationAnnotationProcessor ConfigurationClassPostProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor AutowiredAnnotationBeanPostProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor CommonAnnotationBeanPostProcessor
org.springframework.context.event.internalEventListenerProcessor EventListenerMethodProcessor
org.springframework.context.event.internalEventListenerFactory DefaultEventListenerFactory

register 注册了自己的配置类

通过构造ApplicationContext时产生的reader解读这个注解类,并把配置类当成一个AnnotatedGenericBeanDefinition放入map中等待后续实例化。中间处理了一些common的注解信息并填冲到bd里,比如@Lazy,@Primary,@Role,@DependsOn, @Description等

refresh 方法解析

refresh方法中是个模板方法,里面定义了很多阶段操作,其中主要分析以下几个

invokeBeanFactoryPostProcessors(beanFactory)

主要完成了下面一个操作,其中getBeanFactoryPostProcessors()拿的就是我们手动add进去的那个processor列表,因此目前只有一个

第一步:优先遍历这个list,并加入到对应列表中

BeanDefinitionRegistryPostProcessor -> List<BeanDefinitionRegistryPostProcessor> registryProcessors
BeanFactoryPostProcessor -> List<BeanFactoryPostProcessor> regularPostProcessors
           

注意 这里对BeanDefinitionRegistryPostProcessor 会先触发 postProcessBeanDefinitionRegistry 因为可能在这个方法里面需要引入额外的banFactoryPostProcessor类,等待下一步执行

接下来开始按优先级顺序查找并执行beanFactory中目前的registryPostProcessor

此刻bd map中已经有了如下几个内置类:5个内置+1个自己注解类

Spring系列(三) 从refresh看createBean源码解析

第二步:从beanFactory中拿出所有PriorityOrdered BeanDefinitionRegistryPostProcessor的beanName

此时满足条件的只有

ConfigurationClassPostProcessor

, beanFactory.getBean会将它产生出来并放到缓存中

Spring系列(三) 从refresh看createBean源码解析

并执行 处理器对registry的实现逻辑,这里的配置处理器会将目前所有的bd拿出来判断解析,构造所有需要产生的bd并存放起来 (执行了 )

for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
step -> ConfigurationClassPostProcessor
      processConfigBeanDefinitions
           

判断beanDefinition中属性org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass是否有值(不成立,当前还没被设置过值)

然后checkConfigurationClassCandidate(看是不是候选的配置类)

  • 如果是配置类,产生的bd是AnnotatedGenericBean,会满足第一个条件设置好metaData
  • 如果这个bean是自己注册的,有可能是AbstractBeanDefinition类型,那么再看是不是BeanFactoryPostProcessor,BeanPostProcessor,AopInfrastructureBean,EventListenerFactory等特殊类型,不是的化也设置metadata否则直接结束

拿出Configuration注解的属性信息,允许代理bean方法情况下,设置注解属性为full(就是这个时候才添加了标记,对应前面第一次拿是空);如果没有@Configuration,拿出來的config是null,但是当前有@Bean method,else if中标记为lite

Spring系列(三) 从refresh看createBean源码解析

然后用ConfigurationClassParser 去解析配置类的相关信息,包括Component, PropertySources,ComponentScans,ComponentScan, @Import, ImportResource,

等,最终存在ConfigurationClass包装类中

private final Set<ConfigurationClass> importedBy = new LinkedHashSet<>(1);
	private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
	private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
			new LinkedHashMap<>();
	private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
			new LinkedHashMap<>();
	final Set<String> skippedBeanMethods = new HashSet<>();
           

接着ConfigurationClassBeanDefinitionReader 去加载这些信息loadBeanDefinitions到bd map中

再通过registry直接往容器中的singletonObjects中注册一个处理Import注解的处理类 ,没有走beanDefinition->create逻辑

beanName beanClass
org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry org.springframework.context.annotation.ConfigurationClassParser.ImportStack

完成所有import和其他相关注解信息的处理后,相关需要被扫面加载的bd都已经被存放到beanFactory中的bd map中等待被创建了

第三步 再从容器中找出所有beanFactoryPostProcessor (还是只有一个被执行过的configuration处理类)

如果未被执行过或不是Order优先级的,跳过

第四步 从容器中找出所有beanFactoryPostProcessor,不对接口限制

处理所有未处理的process方法,并继续循环获取防止当前又产生新的处理器

第五步 对所有后置处理器(包括特殊的registry和普通beanFactoryPostprocessor)调用接口方法

postProcessBeanFactory

invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
           

ConfigurationClassPostProcessor postProcessBeanFactory

会对当前所有bd找出可能的注解类,只对full属性的类进行如下逻辑

  • CGLIB 增强@Configuration的类 , enhanceConfigurationClasses

    对标记为full的进行ConfigurationClassEnhancer enhance (保证@Bean method都为单例的,如果在方法调用中有多次)

  • 添加 ImportAwareBeanPostProcessor到beanFactory中的list

第六步 最后从容器中找出所有beanFactoryPostProcessor,防止再postProcessBeanFactory时有

新产生并且未处理过

的处理器

如果有的化依然按照优先级顺序加入执行,执行结果只有一个

Spring系列(三) 从refresh看createBean源码解析
registerBeanPostProcessors

与执行beanFactoryPostProcessor方法类似,已然按照优先级顺序从当前容器中找出来所有name执行,没有自定义的化默认只有这两个内置的,且都是PriorityOrder的

List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>();

Spring系列(三) 从refresh看createBean源码解析

把上述处理器找出来并加入到beanFactory中(实际上只是加到了list中,后续可以直接从当前list中获取,不用从容器里拿)----

registerBeanPostProcessors

接着又直接加了一个ApplicationListenerDetector到集合中,未存在singletonObjects中(该类修饰符是默认的,不可在包外访问实例化)

// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
           
finishBeanFactoryInitialization

这是真正创建非懒加载单例bean的方法,调用beanFactory.preInstantiateSingletons()

非FactoryBean的情况下,直接去getBean

先允许提前从提早缓存对象中拿,提早暴露的objects或objectFactories,对于自定义的单例第一次拿不到

Spring系列(三) 从refresh看createBean源码解析

接着经过一系列判断后,开始创建

if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
				
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
           

getSingleton中会再次尝试从缓存单例池中拿,将当前bean标记为正在创建中,然后调用对象工厂方法createBean构造bean,将它加入到单例对象池中,并将提早引用池和工厂池中移除当前bean

Spring系列(三) 从refresh看createBean源码解析

在工厂方法中,先尝试是否可以有处理器提早生成一个对象(默认还是null),调用

applyBeanPostProcessorsBeforeInstantiation ->有值 再applyBeanPostProcessorsAfterInitialization

执行当前所有(beanFactory中的处理器集合)后置处理器的postProcessBeforeInstantiation

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
           

doCreateBean 去执行真正创建bean的过程

createBeanInstance -> 实例化bean对应的class

applyMergedBeanDefinitionPostProcessors

->

  • 两个内置后置处理器CommonAnnotationBeanPostProcessor -> 处理PostConstruct,Predestroy, Resource等注解信息的封装
  • AutowiredAnnotationBeanPostProcessor->

    处理Autowired,Value等注解对应的file,method封装起来

判断是否需要提前暴露该对象引用(用于

解决循环依赖

),加到singletonFactories

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
           

populateBean ->填充bean的属性

  • InstantiationAwareBeanPostProcessor postProcessAfterInstantiationr处理器的调用
  • 判断注入模式resolvedAutowireMode ,AutowireCapableBeanFactory中的几种
  • InstantiationAwareBeanPostProcessor postProcessProperties 用于处理上一步封装好的InjectedElement的信息。包括common的ResourceElement, autowired的AutowiredFieldElement,AutowiredMethodElement等,如果没有要设置进来的对象,会从bean工厂中找,开始进行依赖对象bean的生命周期的创建

initializeBean ->调用初始化方法及生命周期回调

InitDestroyAnnotationBeanPostProcessor 是CommonAnnotationBeanPostProcessor的父接口

Spring系列(三) 从refresh看createBean源码解析
  • invokeAwareMethods -> BeanNameAware、BeanClassLoaderAware,BeanFactoryAware只有这三个接口,那么其他的aware接口是在哪里调用的呢?ApplicationContextAwareProcessor
  • applyBeanPostProcessorsBeforeInitialization

    ->

    注意 这里会调用InitDestroyAnnotationBeanPostProcessor 解析的PostConstruct方法

    ,以及ApplicationContextAwareProcessor 执行所有invoke Aware接口方法
    Spring系列(三) 从refresh看createBean源码解析
  • invokeInitMethods -> 实现了InitializingBean的方法,调用afterPropertiesSet;同时看bd中是否有自定义不重名的init method也调用
  • applyBeanPostProcessorsAfterInitialization

    -> AbstractAutoProxyCreator 会在这里进行aop动态代理包装

至此,bean的创建就已经结束了!