SpringIOC源码解析
迪丽瓦拉
2024-05-26 19:31:48
0

Spring深度学习(一)——IOC的设计理念

  • Spring的核心思想——IOC
  • Spring流程图
  • DEMO编写
  • Spring IoC容器的加载过程
    • 实例化化容器:AnnotationConfigApplicationContext
      • 实例化建BeanDefinition读取器: AnnotatedBeanDefinitionReader
      • BeanDefinition是什么
      • registerPostProcessor方法
      • 创建BeanDefinition扫描器:ClassPathBeanDefinitionScanner
      • 注册配置类为BeanDefinition: register(annotatedClasses)
    • refresh()
      • prepareRefresh
      • ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
      • prepareBeanFactory
      • postProcessBeanFactory(beanFactory)
      • invokeBeanFactoryPostProcessors(beanFactory)
      • @Import解析
    • registerBeanPostProcessors(beanFactory);
    • initMessageSource()
    • initApplicationEventMulticaster()
    • onRefresh()
    • registerListeners()
    • finishBeanFactoryInitialization(beanFactory)
      • Spring Bean的生命周期
    • finishRefresh()

从今天开始,我将会和大家一起学习Spring的高级知识和源码相关内容。这部分内容面向的是会使用Spring框架的同学,并且想要深度学习,或者从源码层面进行学习Spring更高级的知识。所以对于Spring基础不好的或者不会使用的同学先去学习一下Spring的基本使用再来看效果会更加好。

作为Java开发,是肯定会用到Spring的,在面试的时候也会问到很多关于Spring的相关问题,可见Spring的重要性。所以学习好Spring是相当有必要的。

在正式开始之前,我还要唠叨几句:

  • 对于想要学习源码的同学,一定要知道学习源码比较忌讳把每一行代码从看一遍,一方面是很浪费时间,另一方面是没有必要。Spring源码有100多万行,根本不可能每一行过,我们要明确主线和分支去学习,先主再从后细。
  • 源码需要多看几次,我们学习的是别人良好的代码风格和思想。
  • 学习源码主要是为了提高我们的阅读代码的能力,并且在我们自己开发的时候能够熟练运用
  • 学习源码让我们对框架有更深层次的掌握,解决工作中的问题。

Spring的核心思想——IOC

学习过Spring的肯定都见过下边的图。
在这里插入图片描述
这张图在官网中Spring版本5就找不到了,因为Spring5更推荐使用Boot开发,而在Boot开发中,上图中的很多东西都是已经封装好了的,不需要我们关心。Boot使我们更关心业务,简化了我们的工作,但是却不利于我们对于Spring的深度学习。

我们的这个系列主要是学习IOC,AOP和事务相关的内容,并不会把上图所有的内容都学习。而这篇文章主要是来聊一聊IOC的核心思想。

为什么要使用Spring容器呢?Spring能发展到今天还被广泛使用的原因是什么呢?

在没有Spring出现之前,当我们需要在A类中使用B类,我们需要在A类中写new B()类似这样的代码。那么A和B类就会出现耦合在一起的情况。这样的代码不利于我们维护,拓展性并不好。那我们可不可以把创建对象的这部分交给其他东西做呢?答案是可以的,这样就诞生了Spring。

Spring中有一个思想叫做控制反转(IOC),就是说我们不需要再使用new B()的这种方式来创建对象,而是Spring中有一个容器,通过反射的方式创建好对象,这就是一个Bean,然后放在容器中,谁需要用的时候就直接来我的容器中拿,不需要再自己主动创建。

Spring流程图

我在学习spring源码的时候画了一个流程图,基本的内容都有了,供大家参考:
在这里插入图片描述

丑是丑了点,大家先凑合看看,后期会进行优化。哈哈!

DEMO编写

我们自己先写一个测试例子。

主配置类:MainConfig:

@Configuration
@ComponentScan(basePackages = {"com.chunqiu.demo.config.bean"})
public class MainConfig {
}

bean Tank:

@Component
public class Tank {
}

bean Car:

@Component
public class Car {private String name;@Autowiredprivate Tank Tank;public String getName() {return name;}public void setName(String name) {this.name = name;}public com.chunqiu.demo.config.bean.Tank getTank() {return Tank;}public void setTank(com.chunqiu.demo.config.bean.Tank tank) {Tank = tank;}public Car() {System.out.println("car 加载");}
}

测试 Test:

public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);Car car = context.getBean("car", Car.class);System.out.println(car.getName());}}

运行测试类的main方法,不报错就算是成功了。

Spring IoC容器的加载过程

实例化化容器:AnnotationConfigApplicationContext

我们从这里开始:

// 加载spring上下文AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);

我们可以先看一下AnnotationConfigApplicationContext的结构关系:
请添加图片描述

创建AnnotationConfigApplicationContext对象:

// 根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少
public AnnotationConfigApplicationContext(Class... annotatedClasses) {//调用构造函数//调用无参构造函数,会先调用父类GenericApplicationContext的构造函数//父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory//本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefi nitionScanner scanner//scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的this();//注册我们的配置类//把传入的类进行注册,这里有两个情况,//传入传统的配置类//传入bean(虽然一般没有人会这么做//看到后面会知道spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配 置类//但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通beanregister(annotatedClasses);//IOC容器刷新接口refresh();}

我们先来为构造方法做一个简单的说明:

  1. 这是一个有参的构造方法,可以接收多个配置类,不过一般情况下,只会传入一个配置类。
  2. 这个配置类有两种情况,一种是传统意义上的带上@Configuration注解的配置类,还有一种是没有 带上@Configuration,但是带有@Component,@Import,@ImportResouce,@Service, @ComponentScan等注解的配置类,在Spring内部把前者称为Full配置类,把后者称之为Lite配置 类。在本源码分析中,有些地方也把Lite配置类称为普通Bean

使用断点调试,通过this()调用此类无参的构造方法,代码到下面:

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {/*** 注解的bean定义读取器*/private final AnnotatedBeanDefinitionReader reader;/*** 类路径下的bean定义扫描器*/private final ClassPathBeanDefinitionScanner scanner;//会隐式调用父类的构造方法,初始化DefaultListableBeanFactorypublic AnnotationConfigApplicationContext() {/*** 创建一个读取注解的Bean定义读取器* 什么是bean定义?BeanDefinition** 完成了spring内部BeanDefinition的注册(主要是后置处理器)*/this.reader = new AnnotatedBeanDefinitionReader(this);/*** 创建BeanDefinition扫描器* 可以用来扫描包或者类,继而转换为bd** spring默认的扫描包不是这个scanner对象* 而是自己new的一个ClassPathBeanDefinitionScanner* spring在执行工程后置处理器ConfigurationClassPostProcessor时,去扫描包时会new一个ClassPathBeanDefinitionScanner** 这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法**/this.scanner = new ClassPathBeanDefinitionScanner(this);}}

首先无参构造方法中就是对读取器reader和扫描器scanner进行了实例化,reader的类型是 AnnotatedBeanDefinitionReader,可以看出它是一个 “打了注解的Bean定义读取器”,scanner的类型是 ClassPathBeanDefinitionScanner,它仅仅是在外面手动调用.scan方法,或者调用参数为String的构造方法,传 入需要扫描的包名才会用到,像这样方式传入的配置类是不会用到这个scanner对象的。 AnnotationConfigApplicationContext类是有继承关系的,会隐式调用父类的构造方法: 下面代码
实例化工厂:DefaultListableBeanFactory

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {private final DefaultListableBeanFactory beanFactory;@Nullableprivate ResourceLoader resourceLoader;private boolean customClassLoader = false;private final AtomicBoolean refreshed = new AtomicBoolean();public GenericApplicationContext() {/*** 调用父类的构造函数,为ApplicationContext spring上下文对象初始beanFactory* 为啥是DefaultListableBeanFactory?我们去看BeanFactory接口的时候* 发DefaultListableBeanFactory是最底层的实现,功能是最全的*/this.beanFactory = new DefaultListableBeanFactory();}
}

DefaultListableBeanFactory的关系图:
请添加图片描述
DefaultListableBeanFactory是相当重要的,从字面意思就可以看出它是一个Bean的工厂,什么是Bean的工厂?当然就是用来生产 和获得Bean的。

实例化建BeanDefinition读取器: AnnotatedBeanDefinitionReader

这一步主要做了两件事:
1.注册内置BeanPostProcessor
2.注册相关的BeanDefinition

让我们把目光回到AnnotationConfigApplicationContext的无参构造方法,让我们看看Spring在初始化 AnnotatedBeanDefinitionReader的时候做了什么:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));}

这里的BeanDefinitionRegistry当然就是AnnotationConfigApplicationContext的实例了,这里又直接调 用了此类其他的构造方法:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");Assert.notNull(environment, "Environment must not be null");//把ApplicationContext对象赋值给AnnotatedBeanDefinitionReaderthis.registry = registry;//用户处理条件注解 @Conditional os.namethis.conditionEvaluator = new ConditionEvaluator(registry, environment, null);//注册一些内置的后置处理器AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}

让我们把目光移动到这个方法的最后一行,进入registerAnnotationConfigProcessors方法:

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, null);}

这又是一个门面方法,再点进去,这个方法的返回值Set,但是上游方法并没有去接收这个返回值,所以这 个方法的返回值也不是很重要了,当然方法内部给这个返回值赋值也不重要了。由于这个方法内容比较多, 这里就把最核心的贴出来,这个方法的核心就是注册Spring内置的多个Bean:

/*** 为我们容器中注册了解析我们配置类的后置处理器ConfigurationClassPostProcessor* 名字叫:org.springframework.context.annotation.internalConfigurationAnnotationProcessor*/if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}
  1. 判断容器中是否已经存在了ConfigurationClassPostProcessor Bean
  2. 如果不存在(当然这里肯定是不存在的),就通过RootBeanDefinition的构造方法获得 ConfigurationClassPostProcessor的BeanDefinition,RootBeanDefinition是BeanDefinition的子类
  3. 执行registerPostProcessor方法,registerPostProcessor方法内部就是注册Bean,当然这里注册 其他Bean也是一样的流程。

BeanDefinition是什么

在这里插入图片描述
BeanMetadataElement接口:BeanDefinition元数据,返回该Bean的来源
AttributeAccessor接口:提供对BeanDefinition属性操作能力。

它是用来描述Bean的,里面存放着关于Bean的一系列信息,比如Bean的作用域,Bean所对应的Class,是 否懒加载,是否Primary等等,这个BeanDefinition也相当重要,我们以后会常常和它打交道

registerPostProcessor方法

private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(beanName, definition);return new BeanDefinitionHolder(definition, beanName);}

这方法为BeanDefinition设置了一个Role,ROLE_INFRASTRUCTURE代表这是spring内部的,并非用户定 义的,然后又调用了registerBeanDefinition方法,再点进去,你会发现它是一个接口,没办法直 接点进去了,首先要知道registry实现类是什么,那么它的实现是什么呢?答案是 DefaultListableBeanFactory:

 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { this.beanFactory.registerBeanDefinition(beanName, beanDefinition); }

这又是一个门面方法,再点进去,核心在于下面两行代码:

//这里就是把beanName作为key,beanDefinition作为value,推到map里面
this.beanDefinitionMap.put(beanName, beanDefinition);
//beanDefinitionNames就是一个List,这里就是把beanName放到List中去
this.beanDefinitionNames.add(beanName);

从这里可以看出DefaultListableBeanFactory就是我们所说的容器了,里面放着beanDefinitionMap, beanDefinitionNames,beanDefinitionMap是一个hashMap,beanName作为Key,beanDefinition作 为Value,beanDefinitionNames是一个集合,里面存放了beanName。

DefaultListableBeanFactory中的beanDefinitionMap,beanDefinitionNames也是相当重要的,以 后会经常看到它,最好看到它,第一时间就可以反应出它里面放了什么数据 这里仅仅是注册,可以简单的理解为把一些原料放入工厂,工厂还没有真正的去生产。 上面已经介绍过,这里会一连串注册好几个Bean,在这其中最重要的一个Bean(没有之一)就是 BeanDefinitionRegistryPostProcessor Bean。

ConfigurationClassPostProcessor实现BeanDefinitionRegistryPostProcessor接口, BeanDefinitionRegistryPostProcessor接口又扩展了BeanFactoryPostProcessor接口, BeanFactoryPostProcessor是Spring的扩展点之一,ConfigurationClassPostProcessor是Spring极 为重要的一个类,必须牢牢的记住上面所说的这个类和它的继承关系。

请添加图片描述
除了注册了ConfigurationClassPostProcessor,还注册了其他Bean,其他Bean也都实现了其他接口,比 如BeanPostProcessor等。 BeanPostProcessor接口也是Spring的扩展点之一。 至此,实例化AnnotatedBeanDefinitionReader reader分析完毕。

创建BeanDefinition扫描器:ClassPathBeanDefinitionScanner

由于常规使用方式是不会用到AnnotationConfigApplicationContext里面的scanner的,这里的scanner 仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法。所以这里就不看 scanner是如何被实例化的了。

注册配置类为BeanDefinition: register(annotatedClasses)

register(annotatedClasses);

这里传进去的是一个数组,最终会循环调用如下方法:

 void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,@Nullable Class[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {//存储@Configuration注解注释的类//AnnotatedGenericBeanDefinition可以理解为一种数据结构,是用来描述Bean的,这里的作用就是把传入的标记了注解 的类//转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);//判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;}abd.setInstanceSupplier(instanceSupplier);//解析bean的作用域,如果没有设置的话,默认为单例ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);abd.setScope(scopeMetadata.getScopeName());//获得beanNameString beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));//解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,DescriptionAnnotationConfigUtils.processCommonDefinitionAnnotations(abd);if (qualifiers != null) {//可以传入qualifier数组,所以需要循环处理for (Class qualifier : qualifiers) {//Primary注解优先if (Primary.class == qualifier) {abd.setPrimary(true);}//Lazy注解else if (Lazy.class == qualifier) {abd.setLazyInit(true);}else {//其他,AnnotatedGenericBeanDefinition有个Map属性,直接push进去abd.addQualifier(new AutowireCandidateQualifier(qualifier));}}}for (BeanDefinitionCustomizer customizer : definitionCustomizers) {customizer.customize(abd);}BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);//注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,//DefaultListableBeanFactory维护着一系列信息,比如beanDefinitionNames,beanDefinitionMap//beanDefinitionNames是一个List,用来保存beanName//beanDefinitionMap是一个Map,用来保存beanName和beanDefinitionBeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);}

在这里又要说明下,以常规方式去注册配置类,此方法中除了第一个参数,其他参数都是默认值。 1. 通过AnnotatedGenericBeanDefinition的构造方法,获得配置类的BeanDefinition,这里是不是 似曾相似,在注册ConfigurationClassPostProcessor类的时候,也是通过构造方法去获得 BeanDefinition的,只不过当时是通过RootBeanDefinition去获得,现在是通过 AnnotatedGenericBeanDefinition去获得。
2. 判断需不需要跳过注册,Spring中有一个@Condition注解,如果不满足条件,就会跳过这个类的 注册。
3. 然后是解析作用域,如果没有设置的话,默认为单例。
4. 获得BeanName。
5. 解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary, DependsOn,Role,Description。
6. 限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理论上 是任何注解,这里没有判断注解的有效性)。
7. 把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中(这个不是很重 要,可以简单的理解为方便传参)。
8. 注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册:

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.String beanName = definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// Register aliases for bean name, if any.String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);}}}

这个registerBeanDefinition是不是又有一种似曾相似的感觉,没错,在上面注册Spring内置的Bean的时 候,已经解析过这个方法了,这里就不重复了,此时,让我们再观察下beanDefinitionMap beanDefinitionNames两个变量,除了Spring内置的Bean,还有我们传进来的Bean,这里的Bean当然就 是我们的配置类了:
在这里插入图片描述
到这里注册配置类也分析完毕了。

refresh()

大家可以看到其实到这里,Spring还没有进行扫描,只是实例化了一个工厂,注册了一些内置的Bean和我 们传进去的配置类,真正的大头是在第三行代码:

refresh();

这个方法做了很多事情,让我们点开这个方法:

@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//1:准备刷新上下文环境prepareRefresh();//2:获取告诉子类初始化Bean工厂  不同工厂不同实现ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//3:对bean工厂进行填充属性prepareBeanFactory(beanFactory);try {// 第四:留个子类去实现该接口postProcessBeanFactory(beanFactory);// 调用我们的bean工厂的后置处理器. 1. 会在此将class扫描成beanDefinition  2.bean工厂的后置处理器调用invokeBeanFactoryPostProcessors(beanFactory);// 注册我们bean的后置处理器registerBeanPostProcessors(beanFactory);// 初始化国际化资源处理器.initMessageSource();// 创建事件多播器initApplicationEventMulticaster();// 这个方法同样也是留个子类实现的springboot也是从这个方法进行启动tomcat的.onRefresh();//把我们的事件监听器注册到多播器上registerListeners();// 实例化我们剩余的单实例bean.finishBeanFactoryInitialization(beanFactory);// 最后容器刷新 发布刷新事件(Spring cloud也是从这里启动的)finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception  encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}

prepareRefresh

从命名来看,就知道这个方法主要做了一些刷新前的准备工作,和主流程关系不大,主要是保存了容器的启动时间,启动标志等。

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()

这个方法和主流程关系也不是很大,可以简单的认为,就是把beanFactory取出来而已。XML模式下会在这里读取BeanDefinition

prepareBeanFactory

//还是一些准备工作,添加了两个后置处理器:ApplicationContextAwareProcessor,ApplicationListenerDetector
//还设置了 忽略自动装配 和 允许自动装配 的接口,如果不存在某个bean的时候,spring就自动注册singleton bean
//还设置了bean表达式解析器 等
prepareBeanFactory(beanFactory);

这代码相比前面两个就比较重要了,我们需要点进去好好看看,做了什么操作:

/*** 为我们的bean工厂填充内部属性* @param beanFactory the BeanFactory to configure*/protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {//设置bean工厂的类加载器为当前application应用的加载器beanFactory.setBeanClassLoader(getClassLoader());//为bean工厂设置我们标准的SPEL表达式解析器对象StandardBeanExpressionResolverbeanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));//为我们的bean工厂设置了一个propertityEditor 属性资源编辑器对象(用于后面的给bean对象赋值使用)beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));//注册了一个完整的ApplicationContextAwareProcessor 后置处理器用来处理ApplicationContextAware接口的回调方法beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));/**** 忽略以下接口的bean的 接口函数方法。 在populateBean时* 因为以下接口都有setXXX方法, 这些方法不特殊处理将会自动注入容器中的bean*/beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);/*** 当注册了依赖解析后,例如当注册了对 BeanFactory.class 的解析依赖后,* 当 bean 的属性注 入的时候, 一旦检测到属性为 BeanFactory 类型便会将 beanFactory 的实例注入进去。* 知道为什么可以* @Autowired* ApplicationContext  applicationContext  就是因为这里设置了*/beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);//注册了一个事件监听器探测器后置处理器接口beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// 处理aspectj的if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}//注册了bean工厂的内部的beanif (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {//环境beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {//环境系统属性beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {//系统环境beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}}

主要做了如下的操作:
1. 设置了一个类加载器
2. 设置了bean表达式解析器
3. 添加了属性编辑器的支持
4. 添加了一个后置处理器:ApplicationContextAwareProcessor,此后置处理器实现了BeanPostProcessor接口
5. 设置了一些忽略自动装配的接口
6. 设置了一些允许自动装配的接口,并且进行了赋值操作
7. 在容器中还没有XX的bean的时候,帮我们注册beanName为XX的singleton bean

postProcessBeanFactory(beanFactory)

// 第四:留个子类去实现该接口
postProcessBeanFactory(beanFactory);

这是一个空方法,可能以后Spring会进行扩展。

invokeBeanFactoryPostProcessors(beanFactory)

// 调用我们的bean工厂的后置处理器. 1. 会在此将class扫描成beanDefinition  2.bean工厂的后置处理器调用
invokeBeanFactoryPostProcessors(beanFactory);
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {//  获取两处存储BeanFactoryPostProcessor的对象 传入供接下来的调用//  1.当前Bean工厂,2.和我们自己调用addBeanFactoryPostProcessor的自定义BeanFactoryPostProcessor//getBeanFactoryPostProcessors spring允许我们手动添加BeanFactoryPostProcessor
//即:annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX);PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}}

让我们看看第一个小方法的第二个参数:

public List getBeanFactoryPostProcessors() {return this.beanFactoryPostProcessors;}

这里获得的是BeanFactoryPostProcessor,当我看到这里的时候,愣住了,通过IDEA的查找引用功能,我发现这个集合永远都是空的, 根本没有代码为这个集合添加数据,很久都没有想通,后来才知道我们在外部可以手动添加一个后置处理器,而不是交给Spring去扫描, 即:

annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX);

只有这样,这个集合才不会为空。

让我们点开invokeBeanFactoryPostProcessors方法:

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {//调用BeanDefinitionRegistryPostProcessor的后置处理器 Begin// 定义已处理的后置处理器Set processedBeans = new HashSet<>();//判断我们的beanFactory实现了BeanDefinitionRegistry(实现了该结构就有注册和获取Bean定义的能力)//beanFactory是DefaultListableBeanFactory,是BeanDefinitionRegistry的实现类,所以肯定满足ifif (beanFactory instanceof BeanDefinitionRegistry) {//强行把我们的bean工厂转为BeanDefinitionRegistry,因为待会需要注册Bean定义BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;//保存BeanFactoryPostProcessor类型的后置   BeanFactoryPostProcessor 提供修改List regularPostProcessors = new ArrayList<>();//保存BeanDefinitionRegistryPostProcessor类型的后置处理器 BeanDefinitionRegistryPostProcessor 提供注册List registryProcessors = new ArrayList<>();//循环我们传递进来的beanFactoryPostProcessors 正常情况下,beanFactoryPostProcessors肯定没有数据// 因为beanFactoryPostProcessors是获得手动添加的,而不是spring扫描的// 只有手动调用annotationConfigApplicationContext.addBeanFactoryPostProcessor(XXX)才会有数据for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {//判断我们的后置处理器是不是BeanDefinitionRegistryPostProcessor// 扩展了BeanFactoryPostProcessor,所以这里先要判断是不是BeanDefinitionRegistryPostProcessor// 是的话,直接执行postProcessBeanDefinitionRegistry方法,然后把对象装到registryProcessors里面去if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {//进行强制转化BeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;//调用他作为BeanDefinitionRegistryPostProcessor的处理器的后置方法registryProcessor.postProcessBeanDefinitionRegistry(registry);//添加到我们用于保存的BeanDefinitionRegistryPostProcessor的集合中registryProcessors.add(registryProcessor);}else {//若没有实现BeanDefinitionRegistryPostProcessor 接口,那么他就是BeanFactoryPostProcessor//把当前的后置处理器加入到regularPostProcessors中regularPostProcessors.add(postProcessor);}}//定义一个集合用户保存当前准备创建的BeanDefinitionRegistryPostProcessorList currentRegistryProcessors = new ArrayList<>();//第一步:去容器中获取BeanDefinitionRegistryPostProcessor的bean的处理器名称String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);//循环筛选出来的匹配BeanDefinitionRegistryPostProcessor的类型名称// 获得实现BeanDefinitionRegistryPostProcessor接口的类的BeanName:org.springframework.context.annotatio n.internalConfigurationAnnotationProcessor// 并且装入数组postProcessorNames,我理解一般情况下,只会找到一个// 这里又有一个坑,为什么我自己创建了一个实现BeanDefinitionRegistryPostProcessor接口的类,也打上了@Compon ent注解// 配置类也加上了@Component注解,但是这里却没有拿到// 因为直到这一步,Spring还没有去扫描,扫描是在ConfigurationClassPostProcessor类中完成的,也就是下面的第一 个// invokeBeanDefinitionRegistryPostProcessors方法for (String ppName : postProcessorNames) {//判断是否实现了PriorityOrdered接口的if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {//显示的调用getBean()的方式获取出该对象然后加入到currentRegistryProcessors集合中去//获得ConfigurationClassPostProcessor类,并且放到currentRegistryProcessors//ConfigurationClassPostProcessor是很重要的一个类,它实现了BeanDefinitionRegistryPostProcessor接口//BeanDefinitionRegistryPostProcessor接口又实现了BeanFactoryPostProcessor接口//ConfigurationClassPostProcessor是极其重要的类//里面执行了扫描Bean,Import,ImportResouce等各种操作//用来处理配置类(有两种情况 一种是传统意义上的配置类,一种是普通的bean)的各种逻辑currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));//同时也加入到processedBeans集合中去processedBeans.add(ppName);}}//对currentRegistryProcessors集合中BeanDefinitionRegistryPostProcessor进行排序sortPostProcessors(currentRegistryProcessors, beanFactory);// 把当前的加入到总的里面去//合并Processors,为什么要合并,因为registryProcessors是装载BeanDefinitionRegistryPostProcessor的//一开始的时候,spring只会执行BeanDefinitionRegistryPostProcessor独有的方法//而不会执行BeanDefinitionRegistryPostProcessor父类的方法,即BeanFactoryProcessor的方法//所以这里需要把处理器放入一个集合中,后续统一执行父类的方法registryProcessors.addAll(currentRegistryProcessors);/*** 在这里典型的BeanDefinitionRegistryPostProcessor就是ConfigurationClassPostProcessor* 用于进行bean定义的加载 比如我们的包扫描,@import  等等。。。。。。。。。*///Spring热插播的体现,像ConfigurationClassPostProcessor就相当于一个组件,Spring很多事情就是交给组件去管理invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);//调用完之后,马上clea掉currentRegistryProcessors.clear();
//---------------------------------------调用内置实现PriorityOrdered接口ConfigurationClassPostProcessor完毕--优先级No1-End----------------------------------------------------------------------------------------------------------------------------// 再次根据BeanDefinitionRegistryPostProcessor获得BeanName,看这个BeanName是否已经被执行过了,有没有实现O rdered接口// 如果没有被执行过,也实现了Ordered接口的话,把对象推送到currentRegistryProcessors,名称推送到processedBeans// 如果没有实现Ordered接口的话,这里不把数据加到currentRegistryProcessors,processedBeans中,后续再做处理// 这里才可以获得我们定义的实现了BeanDefinitionRegistryPostProcessor的Bean//去容器中获取BeanDefinitionRegistryPostProcessor的bean的处理器名称(内置的和上面注册的)postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);//循环上一步获取的BeanDefinitionRegistryPostProcessor的类型名称for (String ppName : postProcessorNames) {//表示没有被处理过,且实现了Ordered接口的if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {//显示的调用getBean()的方式获取出该对象然后加入到currentRegistryProcessors集合中去currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));//同时也加入到processedBeans集合中去processedBeans.add(ppName);}}//对currentRegistryProcessors集合中BeanDefinitionRegistryPostProcessor进行排序sortPostProcessors(currentRegistryProcessors, beanFactory);//把他加入到用于保存到registryProcessors中registryProcessors.addAll(currentRegistryProcessors);//调用他的后置处理方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);//调用完之后,马上clea掉currentRegistryProcessors.clear();
//-----------------------------------------调用自定义Order接口BeanDefinitionRegistryPostProcessor完毕-优先级No2-End-----------------------------------------------------------------------------------------------------------------------------//调用没有实现任何优先级接口的BeanDefinitionRegistryPostProcessor//定义一个重复处理的开关变量 默认值为trueboolean reiterate = true;//第一次就可以进来while (reiterate) {//进入循环马上把开关变量给改为falsereiterate = false;//去容器中获取BeanDefinitionRegistryPostProcessor的bean的处理器名称postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);//循环上一步获取的BeanDefinitionRegistryPostProcessor的类型名称for (String ppName : postProcessorNames) {//没有被处理过的if (!processedBeans.contains(ppName)) {//显示的调用getBean()的方式获取出该对象然后加入到currentRegistryProcessors集合中去currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));//同时也加入到processedBeans集合中去processedBeans.add(ppName);//再次设置为truereiterate = true;}}//对currentRegistryProcessors集合中BeanDefinitionRegistryPostProcessor进行排序sortPostProcessors(currentRegistryProcessors, beanFactory);//把他加入到用于保存到registryProcessors中registryProcessors.addAll(currentRegistryProcessors);//调用他的后置处理方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);//进行clearcurrentRegistryProcessors.clear();}
//-----------------------------------------调用没有实现任何优先级接口自定义BeanDefinitionRegistryPostProcessor完毕--End-----------------------------------------------------------------------------------------------------------------------------//调用 BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);//调用BeanFactoryPostProcessor 自设的(没有)invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {//若当前的beanFactory没有实现了BeanDefinitionRegistry 说明没有注册Bean定义的能力// 那么就直接调用BeanDefinitionRegistryPostProcessor.postProcessBeanFactory方法invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}//-----------------------------------------所有BeanDefinitionRegistryPostProcessor调用完毕--End-----------------------------------------------------------------------------------------------------------------------------//-----------------------------------------处理BeanFactoryPostProcessor --Begin-----------------------------------------------------------------------------------------------------------------------------//获取容器中所有的 BeanFactoryPostProcessorString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);//保存BeanFactoryPostProcessor类型实现了priorityOrderedList priorityOrderedPostProcessors = new ArrayList<>();//保存BeanFactoryPostProcessor类型实现了Ordered接口的List orderedPostProcessorNames = new ArrayList<>();//保存BeanFactoryPostProcessor没有实现任何优先级接口的List nonOrderedPostProcessorNames = new ArrayList<>();for (String ppName : postProcessorNames) {//processedBeans包含的话,表示在上面处理BeanDefinitionRegistryPostProcessor的时候处理过了if (processedBeans.contains(ppName)) {// skip - already processed in first phase above}//判断是否实现了PriorityOrdered 优先级最高else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}//判断是否实现了Ordered  优先级 其次else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}//没有实现任何的优先级接口的  最后调用else {nonOrderedPostProcessorNames.add(ppName);}}//  排序sortPostProcessors(priorityOrderedPostProcessors, beanFactory);// 先调用BeanFactoryPostProcessor实现了 PriorityOrdered接口的invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);//再调用BeanFactoryPostProcessor实现了 Ordered.List orderedPostProcessors = new ArrayList<>();for (String postProcessorName : orderedPostProcessorNames) {orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);//调用没有实现任何方法接口的List nonOrderedPostProcessors = new ArrayList<>();for (String postProcessorName : nonOrderedPostProcessorNames) {nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
//-----------------------------------------处理BeanFactoryPostProcessor --End-----------------------------------------------------------------------------------------------------------------------------// Clear cached merged bean definitions since the post-processors might have// modified the original metadata, e.g. replacing placeholders in values...beanFactory.clearMetadataCache();//------------------------- BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor调用完毕 --End-----------------------------------------------------------------------------------------------------------------------------}

首先判断beanFactory是不是BeanDefinitionRegistry的实例,当然肯定是的,然后执行如下操作:

  1. 定义了一个Set,装载BeanName,后面会根据这个Set,来判断后置处理器是否被执行过了

  2. 定义了两个List,一个是regularPostProcessors,用来装载BeanFactoryPostProcessor,一个是registryProcessors用来装载 BeanDefinitionRegistryPostProcessor,其中BeanDefinitionRegistryPostProcessor扩展了BeanFactoryPostProcessor。 BeanDefinitionRegistryPostProcessor有两个方法,一个是独有的postProcessBeanDefinitionRegistry方法,一个是父类的 postProcessBeanFactory方法。

  3. 循环传进来的beanFactoryPostProcessors,上面已经解释过了,一般情况下,这里永远都是空的,只有手动add beanFactoryPostProcessor,这里才会有数据。我们假设beanFactoryPostProcessors有数据,进入循环,判断postProcessor是 不是BeanDefinitionRegistryPostProcessor,因为BeanDefinitionRegistryPostProcessor扩展了BeanFactoryPostProcessor, 所以这里先要判断是不是BeanDefinitionRegistryPostProcessor,是的话,执行postProcessBeanDefinitionRegistry方法,然后 把对象装到registryProcessors里面去,不是的话,就装到regularPostProcessors。

  4. 定义了一个临时变量:currentRegistryProcessors,用来装载BeanDefinitionRegistryPostProcessor。

  5. getBeanNamesForType,顾名思义,是根据类型查到BeanNames,这里有一点需要注意,就是去哪里找,点开这个方法的 话,就知道是循环beanDefinitionNames去找,这个方法以后也会经常看到。这里传了 BeanDefinitionRegistryPostProcessor.class,就是找到类型为BeanDefinitionRegistryPostProcessor的后置处理器,并且赋值 给postProcessorNames。一般情况下,只会找到一个,就是 org.springframework.context.annotation.internalConfigurationAnnotationProcessor,也就是 ConfigurationAnnotationProcessor。这个后置处理器在上一节中已经说明过了,十分重要。这里有一个问题,为什么我自己写了 个类,实现了BeanDefinitionRegistryPostProcessor接口,也打上了@Component注解,但是这里没有获得,因为直到这一步, Spring还没有完成扫描,扫描是在ConfigurationClassPostProcessor类中完成的,也就是下面第一个 invokeBeanDefinitionRegistryPostProcessors方法。

  6. 循环postProcessorNames,其实也就是 org.springframework.context.annotation.internalConfigurationAnnotationProcessor,判断此后置处理器是否实现了 PriorityOrdered接口(ConfigurationAnnotationProcessor也实现了PriorityOrdered接口), 如果实现了,把它添加到currentRegistryProcessors这个临时变量中,再放入processedBeans,代表这个后置处理已经被处理过了。当 然现在还没有处理,但是马上就要处理了

  7. 进行排序,PriorityOrdered是一个排序接口,如果实现了它,就说明此后置处理器是有顺序的,所以需要排序。当然目前这里只 有一个后置处理器,就是ConfigurationClassPostProcessor。

  8. 把currentRegistryProcessors合并到registryProcessors,为什么需要合并?因为一开始spring只会执行 BeanDefinitionRegistryPostProcessor独有的方法,而不会执行BeanDefinitionRegistryPostProcessor父类的方法,即 BeanFactoryProcessor接口中的方法,所以需要把这些后置处理器放入一个集合中,后续统一执行BeanFactoryProcessor接口中 的方法。当然目前这里只有一个后置处理器,就是ConfigurationClassPostProcessor。

  9. 可以理解为执行currentRegistryProcessors中的ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry 方法,这就是Spring设计思想的体现了,在这里体现的就是其中的热插拔,插件化开发的思想。Spring中很多东西都是交给插件去 处理的,这个后置处理器就相当于一个插件,如果不想用了,直接不添加就是了。这个方法特别重要,我们后面会详细说来。

  10. 清空currentRegistryProcessors,因为currentRegistryProcessors是一个临时变量,已经完成了目前的使命,所以需要清空, 当然后面还会用到。

  11. 再次根据BeanDefinitionRegistryPostProcessor获得BeanName,然后进行循环,看这个后置处理器是否被执行过了,如果没 有被执行过,也实现了Ordered接口的话,把此后置处理器推送到currentRegistryProcessors和processedBeans中。 这里就可以获得我们定义的,并且打上@Component注解的后置处理器了,因为Spring已经完成了扫描,但是这里需要注意的是,由于 ConfigurationClassPostProcessor在上面已经被执行过了,所以虽然可以通过getBeanNamesForType获得,但是并不会加入到 currentRegistryProcessors和processedBeans。

  12. 处理排序。

  13. 合并Processors,合并的理由和上面是一样的。

  14. 执行我们自定义的BeanDefinitionRegistryPostProcessor。

  15. 清空临时变量。

  16. 在上面的方法中,仅仅是执行了实现了Ordered接口的BeanDefinitionRegistryPostProcessor,这里是执行没有实现Ordered 接口的BeanDefinitionRegistryPostProcessor。

  17. 上面的代码是执行子类独有的方法,这里需要再把父类的方法也执行一次。

  18. 执行regularPostProcessors中的后置处理器的方法,需要注意的是,在一般情况下,regularPostProcessors是不会有数据 的,只有在外面手动添加BeanFactoryPostProcessor,才会有数据。

  19. 查找实现了BeanFactoryPostProcessor的后置处理器,并且执行后置处理器中的方法。和上面的逻辑差不多,不再详细说明。 这就是这个方法中做的主要的事情了,可以说是比较复杂的。但是逻辑还是比较清晰的,在第9步的时候,我说有一个方法会详细说来, 现在就让我们好好看看这个方法究竟做了什么吧。

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {List configCandidates = new ArrayList<>();//获取IOC 容器中目前所有bean定义的名称String[] candidateNames = registry.getBeanDefinitionNames();//循环我们的上一步获取的所有的bean定义信息for (String beanName : candidateNames) {//通过bean的名称来获取我们的bean定义对象BeanDefinition beanDef = registry.getBeanDefinition(beanName);//判断是否有没有解析过if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {if (logger.isDebugEnabled()) {logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);}}//进行正在的解析判断是不是完全的配置类 还是一个非正式的配置类else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {//满足添加 就加入到候选的配置类集合中configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));}}// 若没有找到配置类 直接返回if (configCandidates.isEmpty()) {return;}//对我们的配置类进行Order排序configCandidates.sort((bd1, bd2) -> {int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());return Integer.compare(i1, i2);});// 创建我们通过@CompentScan导入进来的bean name的生成器// 创建我们通过@Import导入进来的bean的名称SingletonBeanRegistry sbr = null;if (registry instanceof SingletonBeanRegistry) {sbr = (SingletonBeanRegistry) registry;if (!this.localBeanNameGeneratorSet) {BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);if (generator != null) {//设置@CompentScan导入进来的bean的名称生成器(默认类首字母小写)也可以自己定义,一般不会this.componentScanBeanNameGenerator = generator;//设置@Import导入进来的bean的名称生成器(默认类首字母小写)也可以自己定义,一般不会this.importBeanNameGenerator = generator;}}}if (this.environment == null) {this.environment = new StandardEnvironment();}//创建一个配置类解析器对象ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);//用于保存我们的配置类BeanDefinitionHolder放入上面筛选出来的配置类Set candidates = new LinkedHashSet<>(configCandidates);//用于保存我们的已经解析的配置类,长度默认为解析出来默认的配置类的集合长度Set alreadyParsed = new HashSet<>(configCandidates.size());//do while 会进行第一次解析do {//真正的解析我们的配置类parser.parse(candidates);parser.validate();//解析出来的配置类Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());configClasses.removeAll(alreadyParsed);// Read the model and create bean definitions based on its contentif (this.reader == null) {this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}// 此处才把@Bean的方法和@Import 注册到BeanDefinitionMap中this.reader.loadBeanDefinitions(configClasses);//加入到已经解析的集合中alreadyParsed.addAll(configClasses);candidates.clear();//判断我们ioc容器中的是不是>候选原始的bean定义的个数if (registry.getBeanDefinitionCount() > candidateNames.length) {//获取所有的bean定义String[] newCandidateNames = registry.getBeanDefinitionNames();//原始的老的候选的bean定义Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));Set alreadyParsedClasses = new HashSet<>();//赋值已经解析的for (ConfigurationClass configurationClass : alreadyParsed) {alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());}for (String candidateName : newCandidateNames) {//表示当前循环的还没有被解析过if (!oldCandidateNames.contains(candidateName)) {BeanDefinition bd = registry.getBeanDefinition(candidateName);//判断有没有被解析过if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&!alreadyParsedClasses.contains(bd.getBeanClassName())) {candidates.add(new BeanDefinitionHolder(bd, candidateName));}}}candidateNames = newCandidateNames;}}//存在没有解析过的 需要循环解析while (!candidates.isEmpty());// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classesif (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());}if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {// Clear cache in externally provided MetadataReaderFactory; this is a no-op// for a shared cache since it'll be cleared by the ApplicationContext.((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();}}
  1. 获得所有的BeanName,放入candidateNames数组。
  2. 循环candidateNames数组,根据beanName获得BeanDefinition,判断此BeanDefinition是否已经被处理过了。
  3. 判断是否是配置类,如果是的话。加入到configCandidates数组,在判断的时候,还会标记配置类属于Full配置类,还是Lite配 置类,这里会引发一连串的知识盲点:
    3.1 当我们注册配置类的时候,可以不加@Configuration注解,直接使用@Component @ComponentScan @Import @ImportResource等注解,Spring把这种配置类称之为Lite配置类, 如果加了@Configuration注解,就称之为Full配置类。
    3.2 如果我们注册了Lite配置类,我们getBean这个配置类,会发现它就是原本的那个配置类,如果我们注册了Full配置类,我们getBean 这个配置类,会发现它已经不是原本那个配置类了,而是已经被cgilb代理的类了。
    3.3 写一个A类,其中有一个构造方法,打印出“你好”,再写一个配置类,里面有两个被@bean注解的方法,其中一个方法new了A类, 并且返回A的对象,把此方法称之为getA,第二个方法又调用了getA方法,如果配置类是Lite配置类,会发现打印了两次“你好”,也就 是说A类被new了两次,如果配置类是Full配置类,会发现只打印了一次“你好”,也就是说A类只被new了一次,因为这个类被cgilb代理 了,方法已经被改写。
  4. 如果没有配置类直接返回。
  5. 处理排序。
  6. 解析配置类,可能是Full配置类,也有可能是Lite配置类,这个小方法是此方法的核心,稍后具体说明。
  7. 在第6步的时候,只是注册了部分Bean,像 @Import @Bean等,是没有被注册的,这里统一对这些进行注册。 下面是解析配置类的过程:
public void parse(Set configCandidates) {/*** 用于来保存延时的ImportSelectors,最最最著名的代表就是我们的SpringBoot自动装配的的类 AutoConfigurationImportSelector*/this.deferredImportSelectors = new LinkedList<>();// 循环配置类for (BeanDefinitionHolder holder : configCandidates) {BeanDefinition bd = holder.getBeanDefinition();try {//真正的解析我们的bean定义 :通过注解元数据 解析if (bd instanceof AnnotatedBeanDefinition) {parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());}else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());}else {parse(bd.getBeanClassName(), holder.getBeanName());}}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);}}//处理我们延时的DeferredImportSelectors w我们springboot就是通过这步进行记载spring.factories文件中的自定装配的对象processDeferredImportSelectors();}

因为可以有多个配置类,所以需要循环处理。我们的配置类的BeanDefinition是AnnotatedBeanDefinition的实例,所以会进入第一个 if:

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {return;}//获取处我们的配置类对象ConfigurationClass existingClass = this.configurationClasses.get(configClass);if (existingClass != null) {//传入进来的配置类是通过其他配置类的Import导入进来的if (configClass.isImported()) {if (existingClass.isImported()) {//需要合并配置existingClass.mergeImportedBy(configClass);}// Otherwise ignore new imported config class; existing non-imported class overrides it.// 所以假如通过@Import导入一个 已存在的配置类 是不允许的,会忽略。return;}else {// Explicit bean definition found, probably replacing an import.// Let's remove the old one and go with the new one.this.configurationClasses.remove(configClass);this.knownSuperclasses.values().removeIf(configClass::equals);}}// Recursively process the configuration class and its superclass hierarchy.递归处理配置类及其超类层次结构。SourceClass sourceClass = asSourceClass(configClass);//真正的进行配置类的解析do {//解析我们的配置类sourceClass = doProcessConfigurationClass(configClass, sourceClass);}while (sourceClass != null);this.configurationClasses.put(configClass, configClass);}

重点在于doProcessConfigurationClass方法,需要特别注意,最后一行代码,会把configClass放入一个Map,会在上面第7步中用到。
在这里插入图片描述

@Nullableprotected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)throws IOException {//递归处理内部类,一般不会写内部类// Recursively process any member (nested) classes firstprocessMemberClasses(configClass, sourceClass);//处理我们的@propertySource注解的 @PropertySource注解用来加载properties文件for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {if (this.environment instanceof ConfigurableEnvironment) {processPropertySource(propertySource);}else {logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +"]. Reason: Environment must implement ConfigurableEnvironment");}}//解析我们的 @ComponentScan 注解//从我们的配置类上解析处ComponentScans的对象集合属性//获得ComponentScan注解具体的内容,ComponentScan注解除了最常用的basePackage之外,还有includeFilters,exc ludeFilters等Set componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);//如果没有打上ComponentScan,或者被@Condition条件跳过,就不再进入这个ifif (!componentScans.isEmpty() &&!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {//循环解析 我们解析出来的AnnotationAttributesfor (AnnotationAttributes componentScan : componentScans) {//把我们扫描出来的类变为bean定义的集合 真正的解析Set scannedBeanDefinitions =this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());//循环处理我们包扫描出来的bean定义for (BeanDefinitionHolder holder : scannedBeanDefinitions) {BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();if (bdCand == null) {bdCand = holder.getBeanDefinition();}//判断当前扫描出来的bean定义是不是一个配置类,若是的话 直接进行递归解析if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {//递归解析 因为@Component算是lite配置类parse(bdCand.getBeanClassName(), holder.getBeanName());}}}}// 处理 @Import annotationsprocessImports(configClass, sourceClass, getImports(sourceClass), true);// 处理 @ImportResource annotations//@Import注解是spring中很重要的一个注解,Springboot大量应用这个注解//@Import三种类,一种是Import普通类,一种是Import ImportSelector,还有一种是Import ImportBeanDefinitionRegistrar//getImports(sourceClass)是获得import的内容,返回的是一个setAnnotationAttributes importResource =AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);if (importResource != null) {String[] resources = importResource.getStringArray("locations");Class readerClass = importResource.getClass("reader");for (String resource : resources) {String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);configClass.addImportedResource(resolvedResource, readerClass);}}// 处理 @Bean methods 获取到我们配置类中所有标注了@Bean的方法Set beanMethods = retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}// 处理配置类接口 默认方法的@BeanprocessInterfaces(configClass, sourceClass);// 处理配置类的父类的 ,循环再解析if (sourceClass.getMetadata().hasSuperClass()) {String superclass = sourceClass.getMetadata().getSuperClassName();if (superclass != null && !superclass.startsWith("java") &&!this.knownSuperclasses.containsKey(superclass)) {this.knownSuperclasses.put(superclass, configClass);// Superclass found, return its annotation metadata and recursereturn sourceClass.getSuperClass();}}// 没有父类解析完成return null;}
  1. 递归处理内部类,一般不会使用内部类。
  2. 处理@PropertySource注解,@PropertySource注解用来加载properties文件。
  3. 获得ComponentScan注解具体的内容,ComponentScan注解除了最常用的basePackage之外,还有includeFilters, excludeFilters等。
  4. 判断有没有被@ComponentScans标记,或者被@Condition条件带过,如果满足条件的话,进入if,进行如下操作:
    4.1 执行扫描操作,把扫描出来的放入set,这个方法稍后再详细说明。
    4.2 循环set,判断是否是配置类,是的话,递归调用parse方法,因为被扫描出来的类,还是一个配置类,有@ComponentScans注解, 或者其中有被@Bean标记的方法 等等,所以需要再次被解析。
  5. 处理@Import注解,@Import是Spring中很重要的一个注解,正是由于它的存在,让Spring非常灵活,不管是Spring内部,还 是与Spring整合的第三方技术,都大量的运用了@Import注解,@Import有三种情况,一种是Import普通类,一种是Import ImportSelector,还有一种是Import ImportBeanDefinitionRegistrar,getImports(sourceClass)是获得import的内容,返回的 是一个set,这个方法稍后再详细说明。
  6. 处理@ImportResource注解。
  7. 处理@Bean的方法,可以看到获得了带有@Bean的方法后,不是马上转换成BeanDefinition,而是先用一个set接收。 我们先来看4.1中的那个方法:
    在这里插入图片描述
public Set parse(AnnotationAttributes componentScan, final String declaringClass) {//扫描器,还记不记在new AnnotationConfigApplicationContext的时候//会调用AnnotationConfigApplicationContext的构造方法//构造方法里面有一句 this.scanner = new ClassPathBeanDefinitionScanner(this);//当时说这个对象不重要,这里就是证明了。常规用法中,实际上执行扫描的只会是这里的scanner对象	ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);//为我们的扫描器设置beanName的生成器对象Class generatorClass = componentScan.getClass("nameGenerator");boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :BeanUtils.instantiateClass(generatorClass));/*** 解析@Scope的ProxyMode属性, 该属性可以将Bean创建问jdk代理或cglib代理*/ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");if (scopedProxyMode != ScopedProxyMode.DEFAULT) {scanner.setScopedProxyMode(scopedProxyMode);}else {Class resolverClass = componentScan.getClass("scopeResolver");scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));}scanner.setResourcePattern(componentScan.getString("resourcePattern"));//设置CompentScan对象的includeFilters 包含的属性for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {for (TypeFilter typeFilter : typeFiltersFor(filter)) {scanner.addIncludeFilter(typeFilter);}}//设置CompentScan对象的excludeFilters 包含的属性for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {for (TypeFilter typeFilter : typeFiltersFor(filter)) {scanner.addExcludeFilter(typeFilter);}}/*** 是否懒加载,此懒加载为componentScan延迟加载所有类*/boolean lazyInit = componentScan.getBoolean("lazyInit");if (lazyInit) {scanner.getBeanDefinitionDefaults().setLazyInit(true);}//包路径com.tuling.iocbeanlifecicleSet basePackages = new LinkedHashSet<>();String[] basePackagesArray = componentScan.getStringArray("basePackages");for (String pkg : basePackagesArray) {String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);Collections.addAll(basePackages, tokenized);}// 从下面的代码可以看出ComponentScans指定扫描目标,除了最常用的basePackages,还有两种方式// 1.指定basePackageClasses,就是指定多个类,只要是与这几个类同级的,或者在这几个类下级的都可以被扫描到,这 种方式其实是spring比较推荐的// 因为指定basePackages没有IDE的检查,容易出错,但是指定一个类,就有IDE的检查了,不容易出错,经常会用一个空 的类来作为basePackageClasses// 2.直接不指定,默认会把与配置类同级,或者在配置类下级的作为扫描目标for (Class clazz : componentScan.getClassArray("basePackageClasses")) {basePackages.add(ClassUtils.getPackageName(clazz));}if (basePackages.isEmpty()) {basePackages.add(ClassUtils.getPackageName(declaringClass));}scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {@Overrideprotected boolean matchClassName(String className) {return declaringClass.equals(className);}});//真正的进行扫描解析return scanner.doScan(StringUtils.toStringArray(basePackages));}
  1. 定义了一个扫描器scanner,还记不记在new AnnotationConfigApplicationContext的时候,会调用 AnnotationConfigApplicationContext的构造方法,构造方法里面有一句 this.scanner = new ClassPathBeanDefinitionScanner(this);当时说这个对象不重要,这里就是证明了。常规用法中,实际上执行扫描的只会是这里的 scanner对象。
  2. 处理includeFilters,就是把规则添加到scanner。
  3. 处理excludeFilters,就是把规则添加到scanner。
  4. 解析basePackages,获得需要扫描哪些包。
  5. 添加一个默认的排除规则:排除自身。
  6. 执行扫描,稍后详细说明。

这里需要做一个补充说明,添加规则的时候,只是把具体的规则放入规则类的集合中去,规则类是一个函数式接口,只定义了一个虚方法 的接口被称为函数式接口,函数式接口在java8的时候大放异彩,这里只是把规则方塞进去,并没有真正执行匹配规则。 我们来看看到底是怎么执行扫描的:

protected Set doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");//创建bean定义的holder对象用于保存扫描后生成的bean定义对象Set beanDefinitions = new LinkedHashSet<>();//循环我们的包路径集合for (String basePackage : basePackages) {//找到候选的ComponentsSet candidates = findCandidateComponents(basePackage);for (BeanDefinition candidate : candidates) {ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);candidate.setScope(scopeMetadata.getScopeName());//设置我们的beanNameString beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);//这是默认配置 autowire-candidateif (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}//获取@Lazy @DependsOn等注解的数据设置到BeanDefinition中if (candidate instanceof AnnotatedBeanDefinition) {AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}//把我们解析出来的组件bean定义注册到我们的IOC容器中(容器中没有才注册)if (checkCandidate(beanName, candidate)) {BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);registerBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;}

因为basePackages可能有多个,所以需要循环处理,最终会进行Bean的注册。下面再来看看findCandidateComponents方法:

public Set findCandidateComponents(String basePackage) {//spring支持component索引技术,需要引入一个组件,因为大部分情况不会引入这个组件 所以不会进入到这个ifif (this.componentsIndex != null && indexSupportsIncludeFilters()) {return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);}else {return scanCandidateComponents(basePackage);}}

Spring支持component索引技术,需要引入一个组件,大部分项目没有引入这个组件,所以会进入scanCandidateComponents方法:

private Set scanCandidateComponents(String basePackage) {Set candidates = new LinkedHashSet<>();try {//把我们的包路径转为资源路径 cn/tulingxueyuan/MainConfigString packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + '/' + this.resourcePattern;//扫描指定包路径下面的所有.class文件Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);boolean traceEnabled = logger.isTraceEnabled();boolean debugEnabled = logger.isDebugEnabled();//需要我们的resources集合for (Resource resource : resources) {if (traceEnabled) {logger.trace("Scanning " + resource);}//判断当的是不是可读的if (resource.isReadable()) {try {MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);//是不是候选的组件if (isCandidateComponent(metadataReader)) {//包装成为一个ScannedGenericBeanDefinitionScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);//并且设置class资源sbd.setResource(resource);sbd.setSource(resource);if (isCandidateComponent(sbd)) {if (debugEnabled) {logger.debug("Identified candidate component class: " + resource);}//加入到集合中candidates.add(sbd);}else {if (debugEnabled) {logger.debug("Ignored because not a concrete top-level class: " + resource);}}}else {if (traceEnabled) {logger.trace("Ignored because not matching any filter: " + resource);}}}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, ex);}}else {if (traceEnabled) {logger.trace("Ignored because not readable: " + resource);}}}}catch (IOException ex) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);}//返回return candidates;}
  1. 把传进来的类似命名空间形式的字符串转换成类似类文件地址的形式,然后在前面加上classpath,即: com.xx=>classpath:com/xx/**/*.class。
  2. 根据packageSearchPath,获得符合要求的文件。
  3. 循环符合要求的文件,进一步进行判断。 最终会把符合要求的文件,转换为BeanDefinition,并且返回。
    在这里插入图片描述

@Import解析

//这个方法内部相当相当复杂,importCandidates是Import的内容,调用这个方法的时候,已经说过可能有三种情况 
//这里再说下,1.Import普通类,2.Import ImportSelector,3.Import ImportBeanDefinitionRegistrar 
//循环importCandidates,判断属于哪种情况 
//如果是普通类,会进到else,调用processConfigurationClass方法 
//这个方法是不是很熟悉,没错,processImports这个方法就是在processConfigurationClass方法中被调用的 
//processImports又主动调用processConfigurationClass方法,是一个递归调用,因为Import的普通类,也有可能被加 了Import注解,@ComponentScan注解 或者其他注解,所以普通类需要再次被解析 
//如果Import ImportSelector就跑到了第一个if中去,首先执行Aware接口方法,所以我们在实现ImportSelector的同 时,还可以实现Aware接口 
//然后判断是不是DeferredImportSelector,DeferredImportSelector扩展了ImportSelector 
//如果不是的话,调用selectImports方法,获得全限定类名数组,在转换成类的数组,然后再调用processImports,又特 么的是一个递归调用... 
//可能又有三种情况,一种情况是selectImports的类是一个普通类,第二种情况是selectImports的类是一个ImportBean DefinitionRegistrar类,第三种情况是还是一个ImportSelector类... 
//所以又需要递归调用 
//如果Import ImportBeanDefinitionRegistrar就跑到了第二个if,还是会执行Aware接口方法,这里终于没有递归了, 会把数据放到ConfigurationClass中的Map importBeanDefini tionRegistrars中去
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,Collection importCandidates, boolean checkForCircularImports) {if (importCandidates.isEmpty()) {return;}if (checkForCircularImports && isChainedImportOnStack(configClass)) {this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));}else {this.importStack.push(configClass);try {//获取我们Import导入进来的所有组件for (SourceClass candidate : importCandidates) {//判断该组件是不是实现了ImportSelector的if (candidate.isAssignable(ImportSelector.class)) {// Candidate class is an ImportSelector -> delegate to it to determine importsClass candidateClass = candidate.loadClass();//实例化我们的SelectImport组件ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);//调用相关的aware方法ParserStrategyUtils.invokeAwareMethods(selector, this.environment, this.resourceLoader, this.registry);//判断是不是延时的DeferredImportSelectors,是这个类型 不进行处理if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {this.deferredImportSelectors.add(new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));}else {//不是延时的//调用selector的selectImportsString[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());// 所以递归解析-- 直到成普通组件Collection importSourceClasses = asSourceClasses(importClassNames);processImports(configClass, currentSourceClass, importSourceClasses, false);}}//判断我们导入的组件是不是ImportBeanDefinitionRegistrar,这里不直接调用,只是解析else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {// Candidate class is an ImportBeanDefinitionRegistrar ->// delegate to it to register additional bean definitionsClass candidateClass = candidate.loadClass();//实例话我们的ImportBeanDefinitionRegistrar对象ImportBeanDefinitionRegistrar registrar =BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);ParserStrategyUtils.invokeAwareMethods(registrar, this.environment, this.resourceLoader, this.registry);//保存我们的ImportBeanDefinitionRegistrar对象 currentSourceClass=所在配置类configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());}else {// 当做配置类再解析,注意这里会标记:importedBy,  表示这是Import的配置的类// 再执行之前的processConfigurationClass()方法 ,this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());processConfigurationClass(candidate.asConfigClass(configClass));}}}catch (BeanDefinitionStoreException ex) {throw ex;}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" +configClass.getMetadata().getClassName() + "]", ex);}finally {this.importStack.pop();}}}

直到这里,才把ConfigurationClassPostProcessor中的processConfigBeanDefinitions方法简单的过了一下。 但是这还没有结束,这里只会解析@Import的Bean而已, 不会注册。

registerBeanPostProcessors(beanFactory);

实例化和注册beanFactory中扩展了BeanPostProcessor的bean。 例如: AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入) RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法) CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。

initMessageSource()

// 初始化国际化资源处理器. 不是主线代码忽略,没什么学习价值。 initMessageSource();

initApplicationEventMulticaster()

创建事件多播器(今天重点不是这里,后续会出一篇文章详细聊)

onRefresh()

模板方法,在容器刷新的时候可以自定义逻辑,不同的Spring容器做不同的事情

registerListeners()

注册监听器(和initApplicationEventMulticaster一样,今天重点不是这里,后续会出一篇文章详细聊)

finishBeanFactoryInitialization(beanFactory)

实例化所有剩余的(非懒加载)单例 比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。 实例化的过程各种BeanPostProcessor开始起作用。

这个方法是用来实例化懒加载单例Bean的,也就是我们的Bean都是在这里被创建出来的(当然我这里说的 的是绝大部分情况是这样的)

我们再进入finishBeanFactoryInitialization这方法,里面有一个beanFactory.preInstantiateSingletons() 方法:

//初始化所有的非懒加载单例 
beanFactory.preInstantiateSingletons();

我们尝试再点进去,这个时候你会发现这是一个接口,好在它只有一个实现类,所以可以我们来到了他的唯 一实现,实现类就是org.springframework.beans.factory.support.DefaultListableBeanFactory,这里面 是一个循环,我们的Bean就是循环被创建出来的,我们找到其中的getBean方法

 getBean(beanName);

这里有一个分支,如果Bean是FactoryBean,如何如何,如果Bean不是FactoryBean如何如何,好在不管 是不是FactoryBean,最终还是会调用getBean方法,所以我们可以毫不犹豫的点进去,点进去之后,你会 发现,这是一个门面方法,直接调用了doGetBean方法:

return doGetBean(name, null, null, false);

再进去,不断的深入,接近我们要寻找的东西。 这里面的比较复杂,但是有我在,我可以直接告诉你,下一步我们要进入哪里,我们要进入

//创建单例beanif (mbd.isSingleton()) {//把beanName 和一个singletonFactory 并且传入一个回调对象用于回调sharedInstance = getSingleton(beanName, () -> {try {//进入创建bean的逻辑return createBean(beanName, mbd, args);}catch (BeansException ex) {//创建bean的过程中发生异常,需要销毁关于当前bean的所有信息destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}

这里面的createBean方法,再点进去啊,但是又点不进去了,这是接口啊,但是别慌,这个接口又只有一 个实现类,所以说 没事,就是干,这个实现类为 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory。 这个实现的方法里面又做了很多事情,我们就不去看了,我就是带着大家找到那几个生命周期的回调到底定 义在哪里就OK了。

try {/*** 该步骤是我们真正的创建我们的bean的实例对象的过程*/Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isDebugEnabled()) {logger.debug("Finished creating instance of bean '" + beanName + "'");}return beanInstance;

再继续深入doCreateBean方法,这个方法又做了一堆一堆的事情,但是值得开心的事情就是 我们已经找到 了我们要寻找的东西了。
创建实例
首先是创建实例,位于:

//创建bean实例化 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化 该方法很复杂也很重要
instanceWrapper = createBeanInstance(beanName, mbd, args);

填充属性
其次是填充属性,位于:

 populateBean(beanName, mbd, instanceWrapper);//填充属性,超级重要

在填充属性下面有一行代码:

exposedObject = initializeBean(beanName, exposedObject, mbd);

继续深入进去。
aware系列接口的回调
aware系列接口的回调位于initializeBean中的invokeAwareMethods方法:

private void invokeAwareMethods(final String beanName, final Object bean) {if (bean instanceof Aware) {//我们的bean实现了BeanNameAwareif (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}//实现了BeanClassLoaderAware接口if (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}//实现了BeanFactoryAwareif (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}}

BeanPostProcessor的postProcessBeforeInitialization方法

@Overridepublic Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//获取我们容器中的所有的bean的后置处理器for (BeanPostProcessor processor : getBeanPostProcessors()) {//挨个调用我们的bean的后置处理器的postProcessBeforeInitializationObject current = processor.postProcessBeforeInitialization(result, beanName);//若只有有一个返回null 那么直接返回原始的if (current == null) {return result;}result = current;}return result;}

afterPropertiesSet init-method
afterPropertiesSet init-method位于initializeBean中的:

invokeInitMethods(beanName, wrappedBean, mbd);

这里面调用了两个方法,一个是afterPropertiesSet方法,一个是init-method方法:

((InitializingBean) bean).afterPropertiesSet(); invokeCustomInitMethod(beanName, bean, mbd);

BeanPostProcessor的postProcessAfterInitialization方法
BeanPostProcessor的postProcessAfterInitialization方法位于initializeBean的

@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//获取我们容器中的所有的bean的后置处理器for (BeanPostProcessor processor : getBeanPostProcessors()) {/*** 在这里是后置处理器的【第九次调用】 aop和事务都会在这里生存代理对象** 【很重要】* 我们AOP @EnableAspectJAutoProxy 为我们容器中导入了 AnnotationAwareAspectJAutoProxyCreator* 我们事务注解@EnableTransactionManagement 为我们的容器导入了 InfrastructureAdvisorAutoProxyCreator* 都是实现了我们的 BeanPostProcessor接口,InstantiationAwareBeanPostProcessor,* 在这里实现的是BeanPostProcessor接口的postProcessAfterInitialization来生成我们的代理对象*/Object current = processor.postProcessAfterInitialization(result, beanName);//若只有有一个返回null 那么直接返回原始的if (current == null) {return result;}result = current;}return result;}

当然在实际的开发中,应该没人会去销毁Spring的应用上下文把,所以剩余的两个销毁的回调就不去找 了。

Spring Bean的生命周期

  1. 实例化Bean对象,这个时候Bean的对象是非常低级的,基本不能够被我们使用,因为连最基本的属性都没有设置,可以理解为 连Autowired注解都是没有解析的;
  2. 填充属性,当做完这一步,Bean对象基本是完整的了,可以理解为Autowired注解已经解析完毕,依赖注入完成了;
  3. 如果Bean实现了BeanNameAware接口,则调用setBeanName方法;
  4. 如果Bean实现了BeanClassLoaderAware接口,则调用setBeanClassLoader方法;
  5. 如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;
  6. 调用BeanPostProcessor的postProcessBeforeInitialization方法;
  7. 如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法;
  8. 如果Bean定义了init-method方法,则调用Bean的init-method方法;
  9. 调用BeanPostProcessor的postProcessAfterInitialization方法;当进行到这一步,Bean已经被准备就绪了,一直停留在应用的 上下文中,直到被销毁;
  10. 如果应用的上下文被销毁了,如果Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destory-method 声明了销毁方法也会被调用。

finishRefresh()

refresh做完之后需要做的其他事情。 清除上下文资源缓存(如扫描中的ASM元数据) 初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle接口的bean并执行start()方法)。 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作

protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning).清除上下文级别的资源缓存(例如来自扫描的ASM元数据)clearResourceCaches();// Initialize lifecycle processor for this context.// 注册lifecycleProcessor 声明周期处理器//  	作用:当ApplicationContext启动或停止时,它会通过LifecycleProcessor来与所有声明的bean的周期做状态更新initLifecycleProcessor();// Propagate refresh to lifecycle processor first.// 为实现了SmartLifecycle并且isAutoStartup 自动启动的Lifecycle调用start()方法getLifecycleProcessor().onRefresh();// Publish the final event.// 发布容器启动完毕事件publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.//  注册当前spring容器到LiveBeansView//  提供servlet(LiveBeansViewServlet)在线查看所有的bean json 、 为了支持Spring Tool Suite的智能提示LiveBeansView.registerApplicationContext(this);}

这里单独介绍下publishEvent:

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {Assert.notNull(event, "Event must not be null");if (logger.isTraceEnabled()) {logger.trace("Publishing event in " + getDisplayName() + ": " + event);}// Decorate event as an ApplicationEvent if necessaryApplicationEvent applicationEvent;if (event instanceof ApplicationEvent) {applicationEvent = (ApplicationEvent) event;}else {applicationEvent = new PayloadApplicationEvent<>(this, event);if (eventType == null) {eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();}}// Multicast right now if possible - or lazily once the multicaster is initialized// 这里是唯一添加早期事件的地方。所以一定要发布事件才能添加早期事件// 只有当执行力refresh-->registerListeners 才会将earlyApplicationEvents赋为null,所以registerListeners之前发布的事件都是早期事件if (this.earlyApplicationEvents != null) {this.earlyApplicationEvents.add(applicationEvent);}else {getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);}// Publish event via parent context as well...// 如果是父容器,也会向父容器里广播一份if (this.parent != null) {if (this.parent instanceof AbstractApplicationContext) {((AbstractApplicationContext) this.parent).publishEvent(event, eventType);}else {this.parent.publishEvent(event);}}}

使用事件广播器广播事件到相应的监听器multicastEvent

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));//从多播器中获取出所有的监听器for (final ApplicationListener listener : getApplicationListeners(event, type)) {//判断多播器中是否支持异步多播的Executor executor = getTaskExecutor();if (executor != null) {//异步播发事件executor.execute(() -> invokeListener(listener, event));}else {//同步播发invokeListener(listener, event);}}}

调用监听器invokeListener

protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {ErrorHandler errorHandler = getErrorHandler();if (errorHandler != null) {try {doInvokeListener(listener, event);}catch (Throwable err) {errorHandler.handleError(err);}}else {doInvokeListener(listener, event);}}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass())) {// Possibly a lambda-defined listener which we could not resolve the generic event type for// -> let's suppress the exception and just log a debug message.Log logger = LogFactory.getLog(getClass());if (logger.isDebugEnabled()) {logger.debug("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}}

这样,当 Spring 执行到 finishRefresh 方法时,就会将 ContextRefreshedEvent 事件推送到 MyRefreshedListener 中。 跟 ContextRefreshedEvent 相似的还有:ContextStartedEvent、ContextClosedEvent、 ContextStoppedEvent,有兴趣的可以自己看看这几个事件的使用场景。 当然,我们也可以自定义监听事件,只需要继承 ApplicationContextEvent 抽象类即可。

相关内容