目录
- 传送门
- 一、前言
- 二、面试回答总结
- 三、源码解析
- 0、前置核心知识
- 1、prepareRefresh(准备刷新容器上下文 )
- 2、obtainFreshBeanFactory(获取初始化BeanFactory)
- 3、prepareBeanFactory(BeanFactory的预准备工作)
- 4、postProcessBeanFactory(BeanFactory后置处理工作)
- 5、invokeBeanFactoryPostProcessors(执行BeanFactoryPostProcessor的方法);
- 6、registerBeanPostProcessors(注册BeanPostProcessors)
- 7、initMessageSource(初始化国际化资源处理器)
- 8、initApplicationEventMulticaster(初始化事件多播器)
- 9、onRefresh(刷新)
- 10、registerListeners(把事件监听器注册到事件多播器上)
- 11、finishBeanFactoryInitialization(实例化所有的非懒加载单例Bean)
- 12、finishRefresh(完成刷新)
传送门
SpringMVC的源码解析(精品)
Spring6的源码解析(精品)
SpringBoot3框架(精品)
MyBatis框架(精品)
MyBatis-Plus
SpringDataJPA
SpringCloudNetflix
SpringCloudAlibaba(精品)
Shiro
SpringSecurity
java的LOG日志框架
Activiti(敬请期待)
JDK8新特性
JDK9新特性
JDK10新特性
JDK11新特性
JDK12新特性
JDK13新特性
JDK14新特性
JDK15新特性
JDK16新特性
JDK17新特性
JDK18新特性
JDK19新特性
JDK20新特性
JDK21新特性
其他技术文章传送门入口
一、前言
由于面试问到的比较多,而且做java开发这块还是需要真正掌握的。现在参考一些资料,总结一下源码分析。
参考视频IT楠哥p17(p26真正开始)-p41视频,视频参考地址- >p17
下面文章不定期更新中…
先放一张概念图,源码解析部分会详细解析。
二、面试回答总结
1、Spring的生命周期
1.1、简单小结
生命周期-对应源码方法
bean对象创建(调用无参构造器) createBeanInstance
属性赋值-bean对象的自定义属性赋值(去找Autowired) populateBean
属性赋值-bean对象的容器属性赋值 (aware回调,aware就是个标识,里面无方法 ,给bean对象中类似Spring本身的BeanFactory这种属性赋值,或者给beanName这个特殊属性赋值) invokeAwareMethod
bean的后置处理器(初始化之前,源码啥都没做,直接返回bean) beanPostProcessor
执行初始化方法(xml的时候需要在配置bean的时候指定初始化方法)invokeInitMethods
bean的后置处理器(初始化之后,源码用了jdk动态代理或者cglib代理,返回代理bean) beanPostProcessor
bean对象就绪可以使用
bean对象销毁(xml的时候需要在配置bean的时候指定销毁方法,或者 容器类.close方法,不用直接关闭程序)
ioc容器关闭
1.2、详细生命周期
1.通过Spring框架的beanFactory工厂利用反射机制创建bean对象;
2.根据set方法或者有参构造方法给bean对象的属性进行依赖注入;
3.判断当前bean对象是否实现相关的aware接口,诸如beanNameAware、beanFactoryAware接口,如果有的话执行对应的方法;
4.执行bean对象的后置处理器postprocessbeforinitialztion
5.执行初始化方法initMethod
6.执行bean对象的后置处理器postprocessafterinitialztion
7.判断当前bean对象是否为单例,是则放到spring对象容器中,多例直接返回bean对象;
8.使用bean对象;
9.关闭容器,调用destroy方法销毁对象。
2、BeanFactory和FactoryBean的区别
都是创建bean的;
前者流水线,后者私人定制;
BeanFactory 是容器ApplicationContext接口的父接口,是Spring内部的最顶层接口,不对程序员开放;
ClassPathXmlApplicationContext 或者 AnnotationConfigApplicationContext 都是BeanFactory 的实现类。
FactoryBean 是一种整合第三方框架的常用机制,和不同bean不同,配置一个FactoryBean类型的bean,在获取bean 的时候得到的并不是class属性中配置的这个类的对象(bean标签里面的class属性通常是配置要new的全类名,最后spring无参构造反射出来的就是这个对象;而这里不这么返回,这里class属性直接配置FactoryBean 的实现类,返回的却是实现类里面的方法),而是getObject()方法的返回值。(这个是FactoryBean接口里面定义的方法,这个方法可以自由实现内容,最后返回泛型T对象)通过这种机制,spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。比如我们整合Mybatis框架创建SqlSessionFactoryBean就是通过FactoryBean机制创建的。
3、Spring用到的设计模式
单模式:Spring默认单例 、
原型模式:指定作用域为prototype,其实本质是克隆、
工厂模式:BeanFactory、
代理模式:AOP、
模板设计模式:抽象类、
观察者模式:监听器
观察者模式:创建bean生命周期以后,在refresh方法中,一个大块专门用来搞监听器、监听事件、多播器(广播器)
装饰器模式:这种通过一个“基础”组件再叠加各种“附加”功能组件的模式,称之为Filter模式
BeanDefinition接口 抽象类模板设计模式,这接口的实现首先都是抽象类,让抽象类规定一些逻辑迫使子类去不同的实现剩余功能。
接口:自上向下 设计的时候,就是设计规约,不需要考虑具体怎么实现,实现是交给实现类处理。所以是从上往下的。
抽象类:自下向上 设计的时候,基本是从下面的实现类抽取出来的,比如 猫、狗 抽象出 动物抽象类,所以是从下往上的。
4、Spring什么时候用单例?什么时候用多例?
当对象含有可改变状态时(在实际应用中该状态会改变),则多例,否则单例。例如dao和service层的数据一般不会有响应的属性改变,所以考虑单例,而controller层会存储很多需要操作的vo类,此时这个对象的状态就会被改变,则需要使用多例,多例也可以防止并发。
Controller中定义一个非静态类变量,不同请求或者不同线程访问这个变量的时候,这个变量值不同,显然线程不安全。(单例线程不安全,会导致属性重复使用),这个时候将Controller加个Scope注解或者这个属性值用ThreadLocal处理。
5、Spring的循环依赖
三级缓存:
singletonObjects,一级缓存,存储的是所有创建好了的单例Bean(A的完全态实例)
earlySingletonObjects,二级缓存,完成实例化,但是还未进行属性注入及初始化的对象(A非完全态实例)
singletonFactories,三级缓存,提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象(A的单例工厂,获取的也是A自己的代理对象)
关键步骤在于三级缓存是在A有AOP代理的时候才会调用,因为A要注入B属性,所以先要把B实例的完全态全部搞定,而B又需要A,所以整个B的实例化 是一口气完成,这个时候,如果A有AOP就需要用到三级缓存,否则二级缓存就够了,B中要拿到A的引用,而且是代理对象的引用,就要通过三级缓存,A的单例工厂结合jdk动态代理或者cglib,拿到A的代理对象的引用,完成B自己的整个创建;最后再返回来A中注入B属性完成,再初始化A,结束A创建。
和AOP有关,第三级缓存的目的是为了延迟代理对象的创建(以应对循环依赖问题)。如果可以在实例化完成后立即创建代理对象,就不需要三级缓存了,所以二级缓存也是可以解决循环依赖的。为啥要额外多添加一层缓存?因为 Spring 的设计原则是在 Bean 初始化完成之后才为其创建代理
参考资料:
三级缓存和循环依赖(不看点源码都看不懂)
这个参考资料应付面试来说写的非常好,如果还是看不懂,可以结合我下面方法11中三级缓存解决循环依赖的详细解析。
我的理解是根据IT楠哥和自己亲自跑debug得出的(我同意IT楠哥的说法),和参考资料不是完全一致,参考资料适合面试八股文,但是不是三级缓存解决循环依赖的本质。
三、源码解析
0、前置核心知识
整体的流程图
思维导图
前置核心知识
首次看可以不看,后面这些接口、抽象类、实现类都需要知道
0.1、BeanDefinition系列
BeanDefinition:
接口,Bean的定义,一个Bean很多信息在里面,有xml、注解(@Component、@Controller等)、配置类(@Configuration标记配置类中的@Bean)、import注解方式,可以将一个Bean转化为BeanDefinition。
BeanDefinition详解
BeanDefinition族谱
import注解方式,会将方法返回的String[]数组里面的类都注入到Spring容器当中,像SpringBoot下面的一些组件模块,都没和启动类一个包下面,就得通过import注入进去。
BeanDefinitionReader
根接口之一,配置文件解析器,将各种配置文件解析成BeanDefinition;里面一个方法的返回值是BeanDefinitionRegistry,这样就和BeanDefinitionRegistry关联起来了
XmlBeanDefinitionReader
类,BeanDefinition加载方式一,是BeanDefinitionReader的实现类,将xml解析成BeanDefinition,并将这些BeanDefinition注册到BeanDefinitionRegistry容器中。
AnnotatedBeanDefinitionReader
类,无直接继承,BeanDefinition加载方式二,将标记有@Component、@Controller、@Service、@Respository的bean解析成BeanDefinition(注意@Configuration配置类里面的@Bean类无法解析),并将这些BeanDefinition注册到BeanDefinitionRegistry容器中。
ConfigurationClassBeanDefinitionReader
类,无直接继承类,该类没有public修饰,程序员不能直接拿来用,BeanDefinition加载方式三,将标记有@Configuration配置类里面的@Bean类解析成BeanDefinition,并将这些BeanDefinition注册到BeanDefinitionRegistry容器中。
ClassPathBeanDefinitionScanner
类,另一套族谱体系和上面加载方式没太大交集,BeanDefinition加载方式四,通过扫描包的方式将bean解析成BeanDefinition,并将这些BeanDefinition注册到BeanDefinitionRegistry容器中。
BeanDefinitionHolder
类,BeanDefinition的持有者,这个类里面的成员变量就是beanDefinition、beanName、aliases(bean别名)
BeanPostProcessor
根接口,Bean的后置处理器,用来修改容器中的BeanDefinition信息,只有两个方法,在bean生命周期里面,bean初始化方法前执行里面的postProcessBeforeInitialization方法,bean初始化方法后执行里面的postProcessAfterInitialization方法;
0.2、BeanFactroy系列
BeanFactroy
根接口,getBean(beanName,Class)获取对象,实际上还有父接口AliasRegistry(别名注册器),下面所有讨论先忽略AliasRegistry
ConfigurableListableBeanFactory
接口,是BeanFactory的子接口,AbstractApplicationContext.refresh()的12方法中第2个方法获取BeanFactory返回了这个接口,多态的应用,实际上获取BeanFactory真正返回的是DefaultListableBeanFactory,该接口在12方法中第5个方法复杂代码里面当做参数来用。
DefaultListableBeanFactory
类,是ConfigurableListableBeanFactory接口、BeanFactory接口、BeanDefinitionRegistry接口的实现类,也就是说BeanFactory的默认实现兵工厂类是DefaultListableBeanFactory。
BeanDefinitionRegistry
根接口,和BeanFactroy平级的接口(看DefaultListableBeanFactory族谱),主要注册BeanDefinition;里面一个方法的参数是BeanDefinition,这样就和BeanDefinition关联起来了,有了BeanDefinition需要容器去储存,传统的map集合方法太少,不太满足需求,所以就引入了BeanDefinitionRegistry,注册方法类比map.put方法,该接口本质就是个容器,实现类的底层也用了map集合,DefaultListableBeanFactory是该接口实现类,是主要储存容器。
BeanFactoryPostProcessor
根接口,函数式接口,BeanFactory的后置处理器,主要修改BeanFactory,例如增加一些BeanPostProcessor从而修改容器中的BeanDefinition信息;只有一个方法postProcessBeanFactory,该方法以ConfigurableListableBeanFactory为参数,这样就和ConfigurableListableBeanFactory关联起来了;该接口在12方法中第5个方法复杂代码里面有主要应用。
BeanDefinitionRegistryPostProcessor
接口,单继承BeanFactoryPostProcessor,也是主要修改BeanFactory,除去继承父接口方法, 自己有一个postProcessBeanDefinitionRegistry方法,该方法以BeanDefinitionRegistry为参数,这样就和BeanDefinitionRegistry关联起来了;该接口在12方法中第5个方法复杂代码里面有主要应用。
ConfigurationClassPostProcessor
类,真正干活的核心类,是BeanDefinitionRegistryPostProcessor接口的实现类,是优先级最高的BeanFactoryPostProcessor,程序中有自定义的@Configuration注解的BeanFactoryPostProcessor实现类,都是先需要该类处理后,才能识别到这些实现类。
AbstractBeanFactory
抽象类,BeanFactory的实现类,有getBean方法、doGetBean方法,单例多例其他作用域的bean创建在这个抽象类中有调用,refresh12方法中第11个方法中出现。
AbstractAutowireCapableBeanFactory
抽象类,继承AbstractBeanFactory,有createBean方法,doCreateBean方法(bean实例化、bean提前暴露三级缓存、bean填充属性、bean初始化),大名鼎鼎的bean生命周期相关、三级缓存相关都在这边,refresh12方法中第11个方法中出现。
0.3、ApplicationContext系列
ApplicationContext
接口,Spring上下文,应用程序的中央接口,一切的spring知识其实都是为了服务该接口;多继承了很多其他接口,是BeanFactory的子接口
AbstractApplicationContext
抽象类,实现了ApplicationContext接口,Spring框架最核心的refresh方法就在该抽象类中
GenericApplicationContext
类,AbstractApplicationContext的主要实现类,整个源码中大量出现并且使用里面的方法。
GenericWebApplicationContext
类,GenericApplicationContext的子类,通用的web环境上下文
ServletWebServerApplicationContext
类,GenericWebApplicationContext的子类,Servlet的web环境上下文,重写了refresh12方法中的onRefresh方法,SpringBoot就是在这边启动的Tomcat
0.4、其他系列
FactoryBean
顶层接口,工厂Bean,核心方法T getObject(),BeanFactory是工厂流程式的生产Bean,FactoryBean则是私人订制,一般用于第三方框架定制自己的Bean,一般这种Bean非常复杂,工厂流程式的生产无法满足,就需要走私人定制,例如SqlSessionFactoryBean,实现了FactoryBean接口,其中getObject方法就是返回了SqlSessionFactoryBean,通过这种机制,spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。
SmartFactoryBean
接口,FactoryBean子接口,有个isEagerInit急切属性,refresh12方法中第11个方法中出现。默认情况下,Spring实例化的时候,只实例化FactoryBean本身,其getObject返回的T对象不会被实例化,是懒加载方式,T对象只有被使用的时候才真正实例化,如果想让T对象非懒加载方式实例化,就需要T对象实现SmartFactoryBean接口,并将isEagerInit属性设置为true。
铁哥小结
统筹上,先有ApplicationContext上下文,然后再设置BeanFactory,BeanFactory是常见的最终Spring容器上下文AnnotationConfigServletWebServerApplicationContext的一个属性。
0.5、入口
入口:
AbstractApplicationContext.refresh()
从SpringBoot找到入口路径:
SpringApplication.run(DemoApplication.class, args);// 进入run方法
->
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);// 连续继续进入run方法
}
->
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();// 创建一个启动上下文,非Spring容器上下文,做一些启动方面相关的处理,只是在boot工程启动时间的临时上下文,内置多播器
ConfigurableApplicationContext context = null;
// 根据系统变量java.awt.headless的值来设置java.headless.mode,缺省值是true,
// 在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式。
// 默认为true,因为大部分的boot项目都不需要外设交互,一旦启动成功就不需要操作。
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);// 拿到一些监听器
listeners.starting(bootstrapContext, this.mainApplicationClass);// 监听器开始工作,发布ApplicationStartingEvent事件
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 获取命令行参数
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 准备环境
Banner printedBanner = printBanner(environment);// 打印banner
// 创建一个Spring上下文,不执行refresh方法
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);// 设置记录步骤的记录器
// 这里会将一些早期事件注册给多播器,并发布一个事件
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 【核心】刷新容器,真正执行了refresh方法,是真正的入口
refreshContext(context);
afterRefresh(context, applicationArguments);// 刷新后处理
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);// 广播启动完成事件
callRunners(context, applicationArguments);// 执行所有的runner,runner机制,实现对应接口,在SpringBoot启动后能做一些初始化工作,比如Redis预热
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
本文以SpringBoot3.1.2中Spring对应版本是6.0.11为例。
先总览的看一下AbstractApplicationContext.refresh代码
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// 记录每一步执行的工具类
// Prepare this context for refreshing.
prepareRefresh();// 1、准备刷新容器上下文
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 2、获取BeanFactory;默认实现是DefaultListableBeanFactory,在创建容器的时候创建的
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);// 3、BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器,BeanPostProcessor和XXXAware自动装配等)
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);// 4、BeanFactory准备工作完成后进行的后置处理工作(留给子类实现,空方法)
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);// 5、执行BeanFactoryPostProcessor的方法;
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);// 6、注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();// 7、初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
// Initialize event multicaster for this context.
initApplicationEventMulticaster(); // 8、初始化事件多播器
// Initialize other special beans in specific context subclasses.
onRefresh();// 9、子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器
// Check for listener beans and register them.
registerListeners(); // 10、注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);// 11、实例化所有的非懒加载单例bean(最最核心方法)
// Last step: publish corresponding event.
finishRefresh();// 12、完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)
}
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();
contextRefresh.end();
}
}
}
下面分别详细讲解这12个方法(其中第11个方法最为重要)。
1、prepareRefresh(准备刷新容器上下文 )
该方法会主要做准备操作,设置初始化的数据和当任何属性资源激活后设置活动的标记。还会保存一些监听器。
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();// 设置Spring容器的启动时间
this.closed.set(false);// 关闭状态为false,就是撤销关闭状态
this.active.set(true);// 激活状态为true,就是开启活跃状态,便于执行任意属性来源的初始化
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
initPropertySources();// 初始化context environment(上下文环境)中的占位符属性来源,就是初始化上下文环境。web容器(Servlet容器,比如SpringMVC)的上下文就是这个时候转到Spring上下文的。
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();// 用来校验我们容器启动必须依赖的环境变量的值,验证环境信息里一些必须存在的属性
// Store pre-refresh ApplicationListeners...
/**
* 创建一个早期事件监听器对象
*/
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
/**
* 创建一个容器用于保存早期待发布的事件集合 什么是早期事件了?
* 就是我们的事件监听器还没有注册到事件多播器上的时候都称为早期事件
*/
this.earlyApplicationEvents = new LinkedHashSet<>();
}
2、obtainFreshBeanFactory(获取初始化BeanFactory)
该方法主要是刷新内部的工厂。实际上就是重新创建一个bean工厂,并设置工厂的一些属性。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();// 刷新bean工厂
return getBeanFactory();// 返回之前容器准备工作的时候创建的的bean工厂也就是DefaultListableBeanFactory(很重要)
}
// 不同的子类,refreshBeanFactory的实现逻辑是不一样的。
// 这里面代码取的是AbstractRefreshableApplicationContext子类的逻辑,可以重复刷新工厂的。
// GenericApplicationContext子类就是另一种逻辑,只能刷新一次工厂,二次刷新抛异常。
@Override
protected final void refreshBeanFactory() throws BeansException {
// 保证了可以多次刷新工厂
if (hasBeanFactory()) {// 如果有BeanFactory
destroyBeans();// 销毁所有的bean
closeBeanFactory();// 关闭工厂
}
/**
* 这里主要是loadBeanDefinition方法,这里是xml配置文件,
* 所以就通过XmlBeanDefinitionReader进行Bean定义信息的读取(相当于读取材料)。
* 之后创建BeanFactory
*/
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
DefaultListableBeanFactory 是ConfigurableListableBeanFactory的实现类,ConfigurableListableBeanFactory是BeanFactory的子接口。也就是说BeanFactory的默认实现兵工厂类是DefaultListableBeanFactory。而且DefaultListableBeanFactory还实现了
BeanDefinitionRegistry接口,这在后面AbstractApplicationContext.refresh()的12个方法中第5个方法invokeBeanFactoryPostProcessors里面很重要。
ApplicationContext接口目前和DefaultListableBeanFactory无直接关系,虽然都有顶层接口BeanFactory。
3、prepareBeanFactory(BeanFactory的预准备工作)
上一步已经把工厂建好了,但是还不能投入使用,因为工厂里什么都没有,还需要配置一些东西。看看这个方法的注释。这里主要是设置刚刚创建的BeanFactory的一些属性。例如类加载器和后置处理器
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());// 设置BeanFactory的类加载器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));// 设置支持SPEL表达式解析器(@Value注解中能支持很多表达式)
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// 为我们的bean工厂设置了一个propertyEditor属性资源编辑器对象(用于后面的给bean对象赋值使用)
// Configure the bean factory with context callbacks.
/**
* 添加部分BeanPostProcessor【ApplicationContextAwareProcessor】,
* 注册ApplicationContextAwareProcessor后置处理器用来处理ApplicationContextAware接口的回调方法
* ApplicationContextAwareProcessor是BeanPostProcessor接口的实现类。
*/
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
/**
* 设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware等,
* 因为ApplicationContextAwareProcessor的invokeAwareInterfaces方法已经把这7个接口的实现工作做了,
* 当Spring将ApplicationContextAwareProcessor注册后,
* 那么在invokeAwarelnterfaces方法中调用的Aware类已经不是普通的bean了,
* 如EnvironmentAware、EmbeddedValueResolverAware等,那么当然需要在Spring做bean的依赖注入的时候忽略它们。
* 这个就是下面ignoreDependencyInterface的作用。
*/
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.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
/**
* 注册可以解析的自动装配;我们能直接在任何组件中自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
* 其他组件中可以通过 @Autowired 直接注册使用。
* 注册了依赖解析,例如当注册BeanFactory.class的解析依赖后,当bean的属性注入的时候,一旦检测到属性为BeanFactory类型便会将beanFactory的实例注入进去。
*/
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
/**
* 添加BeanPostProcessor【ApplicationListenerDetector】后置处理器,
* 在bean初始化前后的一些工作,注册了一个事件监听器探测器后置处理器接口,
* ApplicationListenerDetector可以探测哪些bean是Listener,是Listener的就注册到多波器里面。
*/
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && 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()));
}
// Register default environment beans.
/**
* 给BeanFactory中注册一些能用的组件
*/
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());// 环境信息ConfigurableEnvironment
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());// 系统属性,systemProperties【Map<String, Object>】
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());// 系统环境变量systemEnvironment【Map<String, Object>】
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());// 应用程序启动
}
}
4、postProcessBeanFactory(BeanFactory后置处理工作)
/**
* Modify the application context's internal bean factory after its standard
* initialization. The initial definition resources will have been loaded but no
* post-processors will have run and no derived bean definitions will have been
* registered, and most importantly, no beans will have been instantiated yet.
* <p>This template method allows for registering special BeanPostProcessors
* etc in certain AbstractApplicationContext subclasses.
* @param beanFactory the bean factory used by the application context
*/
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}
允许在上下文子类中对 bean 工厂进行后处理。 留给子类实现,空方法
Spring 开放接口留给子类去实现该接口,主要用来改变 BeanFactory。
比如给 BeanFactory 添加一些自己的 BeanPostProcessor(Bean的后置处理器,简单理解就是修改BeanFactory 的属性)
能够在标准的 bean 工厂 初始化之后修改内部的应用程序上下文。所有 bean 定义都将被加载,但尚未实例化任何 bean。这允许在某些 ApplicationContext 实现中注册特殊的 BeanPostProcessor 等(空方法postProcessBeanFactory上的英文翻译)。
我们整个流程看的是AbstractApplicationContext.refresh方法,AbstractApplicationContext是抽象类,实现了ApplicationContext 接口,实际真正运行的时候看具体的Spring容器是什么,也就是看AbstractApplicationContext抽象类的具体实现类。
下面的GenericWebApplicationContext和AnnotationConfigServletWebServerApplicationContext为AbstractApplicationContext抽象类的其中两个实现类。他们将空方法postProcessBeanFactory做了具体的逻辑处理。
如下图,AbstractApplicationContext抽象类的postProcessBeanFactory方法有多个具体的实现类。
不同的Spring容器做不同的操作。比如GenericWebApplicationContext容器的操作会在BeanFactory中添加ServletContextAwareProcessor用于处理ServletContextAware类型的bean初始化的时候调用setServletContext或者setServletConfig方法(跟ApplicationContextAwareProcessor原理一样)。
GenericWebApplicationContext的postProcessBeanFactory方法源码:
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
if (this.servletContext != null) {
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}
AnnotationConfigServletWebServerApplicationContext的postProcessBeanFactory方法源码:
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.postProcessBeanFactory(beanFactory);
// 查看basePackages属性,如果设置了会使用ClassPathBeanDefinitionScanner去扫描basePackages包下的bean并注册
if (this.basePackages != null && this.basePackages.length > 0) {
this.scanner.scan(this.basePackages);
}
// 查看annotatedClasses属性,如果设置了会使用AnnotatedBeanDefinitionReader去注册这些bean
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
5、invokeBeanFactoryPostProcessors(执行BeanFactoryPostProcessor的方法);
实例化并调用所有已注册的 BeanFactoryPostProcessor bean,如果给出,则遵守显式顺序。 必须在单例实例化之前调用。此处逻辑非常复杂,首次看可以跳过不看。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
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 (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
代码中getBeanFactoryPostProcessors(),可以看到Spring启动初始化的时候就有3个BeanFactoryPostProcessors了。
Spring容器中找出实现了BeanFactoryPostProcessor接口的processor并执行。Spring容器会委托给PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法执行。
我们进入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法里面看下
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry registry) {
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();// 解释1
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();// 解释2
// 循环所有的BeanFactoryPostProcessor进行分组,这边分成两组。
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {
registryProcessor.postProcessBeanDefinitionRegistry(registry);// BeanDefinitionRegistryPostProcessor 自己的方法,刚好参数是BeanDefinitionRegistry
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 判断1
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 找到PriorityOrdered最优先级的,实例化BeanDefinitionRegistryPostProcessor,并放到currentRegistryProcessors集合里面。
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);// 排序
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());// 判断1-》执行
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {// 判断2
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 找到Ordered普通排序的,实例化BeanDefinitionRegistryPostProcessor,并放到currentRegistryProcessors集合里面。
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());// 判断2-》执行
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {// 判断3
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));// 找到非排序的,实例化BeanDefinitionRegistryPostProcessor,并放到currentRegistryProcessors集合里面。
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);// 排序
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());// 判断3-》执行
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 注意,这边的执行和上面的执行不一样,BeanDefinitionRegistryPostProcessor是有两个方法的,这里是父接口方法的执行,上面的是自己接口方法的执行。
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 上面的BeanDefinitionRegistryPostProcessor全部处理完成
// 下面的开始BeanFactoryPostProcessor的处理,逻辑类似上面。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 循环所有的postProcessorNames,进行分组,这里分三组
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 二次判断1
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {// 二次判断2
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);// 二次判断3
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);// 排序
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// 二次判断1-》执行
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// 二次判断2-》执行
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);// 二次判断3-》执行
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
先解释两个接口(对应代码里面标记的解释1和解释2):
-
BeanFactoryPostProcessor:主要是修改BeanFactory 属性,例如给 BeanFactory 添加一些自己的 BeanPostProcessor,从而用来修改Spring容器中已经存在的bean的定义,使用ConfigurableListableBeanFactory对bean进行处理(就是BeanFactoryPostProcessor里面方法参数是ConfigurableListableBeanFactory)
-
-
BeanDefinitionRegistryPostProcessor:继承BeanFactoryPostProcessor,作用跟BeanFactoryPostProcessor一样,只不过是使用BeanDefinitionRegistry对bean进行处理(就是BeanDefinitionRegistryPostProcessor里面方法参数是BeanDefinitionRegistry),IT楠哥说,这样设计是为了让Spring更加灵活。
-
注意:
-
在springboot的web程序初始化AnnotationConfigServletWebServerApplicationContext容器时,会初始化内部属性AnnotatedBeanDefinitionReader reader,这个reader构造的时候会在BeanFactory中注册一些post processor,包括BeanPostProcessor和BeanFactoryPostProcessor(比如ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor):
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
-
在使用mybatis时,一般配置了MapperScannerConfigurer的bean,这个bean就是继承的BeanDefinitionRegistryPostProcessor,所以也是这个地方把扫描的mybatis的接口注册到容器中的。
我们再回到PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法里面看,该方法处理的主要逻辑如下:
从Spring容器中找出BeanDefinitionRegistryPostProcessor类型的bean(这些processor是在容器刚创建的时候通过构造AnnotatedBeanDefinitionReader的时候注册到容器中的),然后按照优先级分别执行,优先级的逻辑如下:
- 实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor先全部找出来,然后排序后依次执行(对应代码里面标记的判断1)
- 实现Ordered接口的BeanDefinitionRegistryPostProcessor找出来,然后排序后依次执行(对应代码里面标记的判断2)
- 没有实现PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor找出来执行并依次执行(对应代码里面标记的判断3)
接下来从Spring容器内查找BeanFactoryPostProcessor接口的实现类,然后执行(如果processor已经执行过,则忽略),这里的查找规则跟上面查找BeanDefinitionRegistryPostProcessor一样,先找PriorityOrdered,然后是Ordered,最后是两者都没。
我们进入到第一个invokeBeanDefinitionRegistryPostProcessors方法中看下(对应代码里面标记的判断1-》执行)
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanDefinitionRegistry(registry);// ConfigurationClassPostProcessor是优先级最高的,将第一个执行。
postProcessBeanDefRegistry.end();
}
}
这里需要说明的是ConfigurationClassPostProcessor这个processor是优先级最高的被执行的processor(实现了PriorityOrdered接口)。
我们进入postProcessor.postProcessBeanDefinitionRegistry(registry)方法中看下,这个时候有很多个实现类,我们选择ConfigurationClassPostProcessor。
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);// 核心处理逻辑
}
我们继续进入processConfigBeanDefinitions(registry)方法中看下
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
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));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry _sbr) {
sbr = _sbr;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
parser.parse(candidates);// 核心parse
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = Set.of(candidateNames);
Set<String> 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 classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
// Store the PropertySourceDescriptors to contribute them Ahead-of-time if necessary
this.propertySourceDescriptors = parser.getPropertySourceDescriptors();
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory 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.clearCache();
}
}
ConfigurationClassPostProcessor会去BeanFactory中找出所有有@Configuration注解的bean,然后使用ConfigurationClassParser去解析这个类。
ConfigurationClassParser内部有个Map<ConfigurationClass, ConfigurationClass>类型的configurationClasses属性用于保存解析的类,ConfigurationClass是一个对要解析的配置类的封装,内部存储了配置类的注解信息、被@Bean注解修饰的方法、@ImportResource注解修饰的信息、ImportBeanDefinitionRegistrar等都存储在这个封装类中。
这里ConfigurationClassPostProcessor最先被处理还有另外一个原因是如果程序中有自定义的BeanFactoryPostProcessor,那么这个PostProcessor首先得通过ConfigurationClassPostProcessor被解析出来,然后才能被Spring容器找到并执行。(ConfigurationClassPostProcessor不先执行的话,这个Processor是不会被解析的,不会被解析的话也就不会执行了)。
我们进入parser.parse(candidates)方法看下(上面代码中标记有核心parse)
public void parse(Set<BeanDefinitionHolder> configCandidates) {
for (BeanDefinitionHolder holder : configCandidates) {
BeanDefinition bd = holder.getBeanDefinition();
try {
if (bd instanceof AnnotatedBeanDefinition annotatedBeanDef) {
parse(annotatedBeanDef.getMetadata(), holder.getBeanName());// 核心逻辑
}
else if (bd instanceof AbstractBeanDefinition abstractBeanDef && abstractBeanDef.hasBeanClass()) {
parse(abstractBeanDef.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);
}
}
this.deferredImportSelectorHandler.process();
}
我们来到了ConfigurationClassParser内部的parse方法,可以看到根据BeanDefinition不同类型,进行再次parse,我们点第一个parse进去
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);// 核心逻辑
}
继续点进去
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
if (configClass.isImported()) {
if (existingClass.isImported()) {
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
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, filter);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);// 核心逻辑
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
我们可以看到doProcessConfigurationClass方法真正的在处理逻辑了,Spring系列框架,方法前面带do往往是真正干活儿的方法。我们点进去看下
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass, filter);
}
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.propertySourceRegistry != null) {
this.propertySourceRegistry.processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
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 recurse
return sourceClass.getSuperClass();
}
}
// No superclass -> processing is complete
return null;
}
其核心逻辑如下:
- 处理@PropertySources注解:进行一些配置信息的解析
- 处理@ComponentScan注解:使用ComponentScanAnnotationParser扫描basePackage下的需要解析的类(@SpringBootApplication注解也包括了@ComponentScan注解,只不过basePackages是空的,空的话会去获取当前@Configuration修饰的类所在的包),并注册到BeanFactory中(这个时候bean并没有进行实例化,而是进行了注册。具体的实例化在finishBeanFactoryInitialization方法中执行)。对于扫描出来的类,递归解析
- 处理@Import注解:先递归找出所有的注解,然后再过滤出只有@Import注解的类,得到@Import注解的值。比如查找@SpringBootApplication注解的@Import注解数据的话,首先发现@SpringBootApplication不是一个@Import注解,然后递归调用修饰了@SpringBootApplication的注解,发现有个@EnableAutoConfiguration注解,再次递归发现被@Import(EnableAutoConfigurationImportSelector.class)修饰,还有@AutoConfigurationPackage注解修饰,再次递归@AutoConfigurationPackage注解,发现被@Import(AutoConfigurationPackages.Registrar.class)注解修饰,所以@SpringBootApplication注解对应的@Import注解有2个,分别是@Import(AutoConfigurationPackages.Registrar.class)和@Import(EnableAutoConfigurationImportSelector.class)。找出所有的@Import注解之后,开始处理逻辑:
–>遍历这些@Import注解内部的属性类集合
–>如果这个类是个ImportSelector接口的实现类,实例化这个ImportSelector,如果这个类也是DeferredImportSelector接口的实现类,那么加入ConfigurationClassParser的deferredImportSelectors属性中让第6步处理。否则调用ImportSelector的selectImports方法得到需要Import的类,然后对这些类递归做@Import注解的处理
–>如果这个类是ImportBeanDefinitionRegistrar接口的实现类,设置到配置类的importBeanDefinitionRegistrars属性中
–>其它情况下把这个类入队到ConfigurationClassParser的importStack(队列)属性中,然后把这个类当成是@Configuration注解修饰的类递归重头开始解析这个类 - 处理@ImportResource注解:获取@ImportResource注解的locations属性,得到资源文件的地址信息。然后遍历这些资源文件并把它们添加到配置类的importedResources属性中
- 处理@Bean注解:获取被@Bean注解修饰的方法,然后添加到配置类的beanMethods属性中
- 处理DeferredImportSelector:处理第3步@Import注解产生的DeferredImportSelector,进行selectImports方法的调用找出需要import的类,然后再调用第3步相同的处理逻辑处理
备注:
- 这里@SpringBootApplication注解被@EnableAutoConfiguration修饰,@EnableAutoConfiguration注解被@Import(EnableAutoConfigurationImportSelector.class)修饰,所以在第3步会找出这个@Import修饰的类EnableAutoConfigurationImportSelector,这个类刚好实现了DeferredImportSelector接口,接着就会在第6步被执行。第6步selectImport得到的类就是自动化配置类。
- EnableAutoConfigurationImportSelector的selectImport方法会在spring-boot-autoconfigure包的META-INF里面的spring.factories文件中找出key为org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的值,有109个,这109个就是所谓的自动化配置类(XXXAutoConfiguration)。(如果引入了mybatis和pagehelper,也会在对应的XXXautoconfigure包的META-INF里面的spring.factories找到EnableAutoConfiguration,这样可能最后得到的自动配置类会大于109个。)然后在过滤排除一下不需要的配置,最后返回实际用到的。
ConfigurationClassParser解析完成之后,被解析出来的类会放到configurationClasses属性中。然后使用ConfigurationClassBeanDefinitionReader去解析这些类。
这个时候这些bean只是被加载到了Spring容器中。下面这段代码是ConfigurationClassBeanDefinitionReader的解析bean过程:这个时候这些bean只是被加载到了Spring容器中。下面这段代码是ConfigurationClassBeanDefinitionReader#loadBeanDefinitions的解析bean过程:
public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
for (ConfigurationClass configClass : configurationModel) {
//对每一个配置类,调用loadBeanDefinitionsForConfigurationClass方法
loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
}
}
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
TrackedConditionEvaluator trackedConditionEvaluator) {
//使用条件注解判断是否需要跳过这个配置类
if (trackedConditionEvaluator.shouldSkip(configClass)) {
//跳过配置类的话在Spring容器中移除bean的注册
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
if (configClass.isImported()) {
//如果自身是被@Import注释所import的,注册自己
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//注册方法中被@Bean注解修饰的bean
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//注册@ImportResource注解注释的资源文件中的bean
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//注册@Import注解中的ImportBeanDefinitionRegistrar接口的registerBeanDefinitions
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
以上为PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法的全部详细流程。
invokeBeanFactoryPostProcessors方法总结:
就是从Spring容器中找出BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor接口的实现类并按照一定的规则顺序进行执行。 其中ConfigurationClassPostProcessor这个BeanDefinitionRegistryPostProcessor优先级最高,它会对项目中的@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理)进行解析,解析完成之后把这些bean注册到BeanFactory中。需要注意的是这个时候注册进来的bean还没有实例化。
下面这图就是对ConfigurationClassPostProcessor后置器的总结:
6、registerBeanPostProcessors(注册BeanPostProcessors)
从Spring容器中找出的BeanPostProcessor接口的bean,并设置到BeanFactory的属性中。之后bean被实例化的时候会调用这个BeanPostProcessor。这里只是注册。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
// 拿到所有的BeanPostProcessor的名字
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// BeanPostProcessorChecker是个检查器,可以检查这个bean是不是一个BeanPostProcessor
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();// 最优先级的
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();// 内部的,合并BeanDefinition的bean后置处理器
List<String> orderedPostProcessorNames = new ArrayList<>();// 排序的
List<String> nonOrderedPostProcessorNames = new ArrayList<>();// 非排序的
// 循环进行分类
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);// 找出MergedBeanDefinitionPostProcessor加入集合中
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);// 排序 最优先级的PostProcessors
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// 注册
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);// 找出MergedBeanDefinitionPostProcessor加入集合中
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);// 排序 排序的PostProcessors
registerBeanPostProcessors(beanFactory, orderedPostProcessors);// 注册
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);// 找出MergedBeanDefinitionPostProcessor加入集合中
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);// 没有顺序,直接注册
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);// 排序 内部的PostProcessors
registerBeanPostProcessors(beanFactory, internalPostProcessors);// 注册
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// 再次增加了ApplicationListenerDetector探测器,之前已经加过一次
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
该方法委托给了PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法执行。这里的过程跟invokeBeanFactoryPostProcessors类似
- 先找出实现了PriorityOrdered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
- 找出实现了Ordered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
- 没有实现PriorityOrdered和Ordered接口的BeanPostProcessor加到BeanFactory的BeanPostProcessor集合中
- 上面三种情况下各自找出是MergedBeanDefinitionPostProcessor的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
这些已经存在的BeanPostProcessor在postProcessBeanFactory方法中已经说明,都是由AnnotationConfigUtils的registerAnnotationConfigProcessors方法注册的。这些BeanPostProcessor包括有AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)、RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)、CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。
如果是自定义的BeanPostProcessor,已经被ConfigurationClassPostProcessor注册到容器内。
这些BeanPostProcessor会在这个方法内被实例化(通过调用BeanFactory的getBean方法,如果没有找到实例化的类,就会去实例化)。
/**
* 往容器中注册了我们的bean的后置处理器
* bean的后置处理器在什么时候进⾏调⽤?在bean的⽣命周期中
* @param beanFactory
* @param applicationContext
*/
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // 去容器中获取所有的BeanPostProcessor的bean名称
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
/**
* beanFactory.getBeanPostProcessorCount()获取的是已经添加在beanFactory的beanPostProcessors集合中的数量
* postProcessorNames.length是beanFactory⼯⼚中BeanPostProcessor个数
* +1 是因为下面又新加了一个
*/
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// 注册了BeanPostProcessorChecker的后置处理器
/**
* 按照BeanPostProcessor实现的优先级接⼝来分离Bean后置处理器
*/
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();// 实现了priorityOrdered接⼝的
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();// 容器内部的
List<String> orderedPostProcessorNames = new ArrayList<>();// 实现了ordered接⼝的
List<String> nonOrderedPostProcessorNames = new ArrayList<>();// 非排序的
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {// 若实现了PriorityOrdered接⼝的
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);// 显示的调⽤getBean流程创建bean的后置处理器
priorityOrderedPostProcessors.add(pp); // 加⼊到集合中
if (pp instanceof MergedBeanDefinitionPostProcessor) {// 判断是否实现了MergedBeanDefinitionPostProcessor
internalPostProcessors.add(pp); // 加⼊到集合中
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {// 判断是否实现了Ordered接⼝的
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// 把实现了priorityOrdered注册到容器中
// Next, register the BeanPostProcessors that implement Ordered.
// 处理实现Ordered的bean后置处理器
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);// 显示调⽤getBean⽅法
orderedPostProcessors.add(pp); // 加⼊到集合中
if (pp instanceof MergedBeanDefinitionPostProcessor) {// 判断是否实现了MergedBeanDefinitionPostProcessor
internalPostProcessors.add(pp);// 加⼊到集合中
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors); // 排序并且注册实现了Order接⼝的后置处理器
// Now, register all regular BeanPostProcessors.
// 处理所有的非排序接⼝的
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);// 注册普通的没有实现任何排序接⼝的
// 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));// 注册ApplicationListenerDetector应⽤监听器探测器的后置处理器
}
7、initMessageSource(初始化国际化资源处理器)
国际化,applicationContext默认是支持国际化的,因为他继承了MessageSource接口所以能够实现国际化。
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();// 拿到工厂
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {// 工厂包含这个名字
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource hms &&
hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());// 设置一个父的MessageSource
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {// 工厂不包含那个名字
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();// new一个MessageSource实例
dms.setParentMessageSource(getInternalParentMessageSource());// 设置一个父的MessageSource
this.messageSource = dms;// 给成员变量赋值这个新的MessageSource实例
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);// 将MessageSource注册到BeanFactory中
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
8、initApplicationEventMulticaster(初始化事件多播器)
在Spring容器中初始化事件广播器,事件广播器用于事件的发布。
程序首先会检查bean工厂中是否有bean的名字和这个常量(applicationEventMulticaster)相同的,如果没有则说明没有那么就使用默认的ApplicationEventMulticaster 的实现:SimpleApplicationEventMulticaster
/**
* 从bean⼯⼚中获取或者直接显示的new⼀个事件多播器赋值给applicatoinContext对象的applicationEventMulticaster属性
* 事件多播器采⽤典型的设计模式就是观察者模式 多播器作为的是⼀个被观察者
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();// 获取bean⼯⼚对象
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {// 判断容器中是否包含了applicationEventMulticaster事件多播器组件
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); // 直接显示的调⽤我们的getBean获取出来赋值给我们的applicationContext对象
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {// 容器中没有的话
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);// 直接new⼀个
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);// 并且注⼊到容器中
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
9、onRefresh(刷新)
一个模板方法,不同的Spring容器做不同的事情。留给子类实现,SpringBoot就是从这个方法进行Tomcat的启动。
比如web程序的容器ServletWebServerApplicationContext中会调用createWebServer方法去创建内置的Servlet容器。
目前SpringBoot只支持3种内置的Servlet容器:
- Tomcat
- Jetty
- Undertow
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
10、registerListeners(把事件监听器注册到事件多播器上)
注册应用的监听器。把事件监听器注册到事件多播器上,就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的。这不会影响到其它监听器bean。在注册完以后,还会将其前期的事件发布给相匹配的监听器。
protected void registerListeners() {
// Register statically specified listeners first.
// 获取容器中所有的监听器对象,从容器中拿到所有已经创建的ApplicationListener
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);// 把监听器挨个的注册到事件多播器上去
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);// 获取bean定义中的监听器对象,获取所有还没有创建的ApplicationListener
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);// 把监听器的名称注册到我们的事件多播器上
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;// 在这⾥获取早期事件
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
// 通过多播器进行播发早期事件
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);// 断点进入
}
}
}
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, null);// 断点进入
}
@Override
public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : ResolvableType.forInstance(event));
Executor executor = getTaskExecutor();// 判断多播器中是否⽀持异步多播的
// 从事件多播器中获取出所有的监听器
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));// 异步播发事件
}
else {
invokeListener(listener, event);// 同步播发-》断点进入
}
}
}
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()) ||
(event instanceof PayloadApplicationEvent payloadEvent &&
matchesClassCastMessage(msg, payloadEvent.getPayload().getClass()))) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception.
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
11、finishBeanFactoryInitialization(实例化所有的非懒加载单例Bean)
实例化BeanFactory中已经被注册但是未实例化的所有实例(懒加载的不需要实例化)。
比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。
实例化的过程各种BeanPostProcessor开始起作用。
此方法为12个方法中最最核心方法,最为重要的方法,面试很多细节都是问的这里面的。此方法需要详细掌握。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {// BeanFactory是否包含ConversionService
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));// 实例化ConversionService
}
// Register a default embedded value resolver if no BeanFactoryPostProcessor
// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {// BeanFactory是否有内嵌值解析器
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
// 添加内嵌值解析器(比如@Value的解析等)
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 加载时植入(这边一般是空的,Spring预留的,SpringCloud有个探针就是这种植入)
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();// 冻结配置(之前的配置都修改好了,这边冻结以后就不能再修改了)
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有非懒加载的单例bean
beanFactory.preInstantiateSingletons();// 断点进入
}
断点进入beanFactory.preInstantiateSingletons()
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 将beanDefinitionNames这些名字拷贝一个副本出来,不动原来成员变量的东西。
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 将BeanDefinition进行合并
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {// 不是抽象的&&单例的&&非懒加载的
if (isFactoryBean(beanName)) {// 是工厂Bean
// &前缀,工厂Bean会优先实例化自己,内部的getObject方法,不会在这边主动调用,本质是个懒加载机制,使用的时候才去真正的拿getObject返回的对象。
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);// 这个前缀就表明是实例化工厂Bean自己,而不是getObject返回的对象。
// 如果想急切的使用getObject返回的对象,那么这里这个返回的对象需要实现SmartFactoryBean接口并且设置isEagerInit(急切属性)为true,SmartFactoryBean是FactoryBean子接口
if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
getBean(beanName);// 真正实例化
}
}
else {// 不是工厂Bean
getBean(beanName);// 真正实例化-》断点进入
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 在上面所有的bean实例化后,这边做找出一些bean做一些处理。
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);// 拿到单例bean
if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {// 找到实现SmartInitializingSingleton 接口的bean
StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
smartSingleton.afterSingletonsInstantiated();// 执行SmartInitializingSingleton 接口中方法
smartInitialize.end();
}
}
}
断点进入getBean(beanName)【核心方法】
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);// 断点继续进入
}
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);// 转化bean名字,比如别名转化为真正的beanname
Object beanInstance;
// Eagerly check singleton cache for manually registered singletons.
// 急切的检查缓存里面是不是有单例,三级缓存核心点
// 从一级或者二级或者三级缓存获取bean,如果触发了从三级缓存获取bean,会从一级缓存删除,放到二级缓存中,并且获取的bean可能是原始bean也可能是代理bean。
// 【循环依赖解决核心:从三个缓存获取逻辑】 getSingleton方法非常重要,是看懂循环依赖解决方案的关键之一。
Object sharedInstance = getSingleton(beanName);// 断点进入-》三级缓存1
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 如果sharedInstance不是FactoryBean,就返回sharedInstance本身,
// 如果是,就是获取FactoryBean的getObject方法返回值T对象,T对象是真正需要实例化的
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);// 断点进入1
}
else {// 缓存里面没有
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 如果正在创建这个bean实例,则抛出异常,这里和循环引用也有关系,比如构造器的循环引用,new A(B),new B(A)。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 有点类似双亲委派机制(我爸是李刚,有事找我爸),先从父工厂里面找,干活儿也想着让父工厂干。
BeanFactory parentBeanFactory = getParentBeanFactory();// 获取父工厂
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// 父工厂没有
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory abf) {
return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);// 父工厂去创建,递归
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);// 这些都是递归了
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);// 这些都是递归了
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);// 这些都是递归了
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
// 上面父工厂也没搞定(或者递归到没有父工厂了),就到了本工厂自己搞定创建了。
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 合并BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);// 检查合并后的BeanDefinition 有没有问题
// Guarantee initialization of beans that the current bean depends on.
// 判断有没有所依赖的bean,比如A依赖B,B依赖C
String[] dependsOn = mbd.getDependsOn();// 找到依赖
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);// 注册依赖bean
try {
getBean(dep);// 优先实例化依赖的bean,这里也是递归
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {// 单例
// createBean并不会去做缓存,getSingleton才是做了缓存的
// 【循环依赖解决核心:存放到三个缓存逻辑】
sharedInstance = getSingleton(beanName, () -> {// 断点进入2
try {
// 循环引用的处理就在createBean中
return createBean(beanName, mbd, args);// 真正核心-》断点进入X
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
// 是拿BeanFactory本身,还是拿BeanFactory的getObject方法返回的T对象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {// 多例
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);// 在创建前先标识一下,表示要创建了
prototypeInstance = createBean(beanName, mbd, args);// 创建,多例bean不会被缓存,而单例会缓存。
}
finally {
afterPrototypeCreation(beanName);// 移除标识,标识创建完成了
}
// 是拿BeanFactory本身,还是拿BeanFactory的getObject方法返回的T对象
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {// 其他作用域,非单例非多例,代码类似多例的
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
// 将bean做适配,里面就是判断是不是需要转化,如果需要就将bean做转化。Spring的灵活。
return adaptBeanInstance(name, beanInstance, requiredType);
}
我们看下beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);// 断点进入1
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {// 是不是FactoryBean的引用(本质判断是不是以&开头的)
if (beanInstance instanceof NullBean) {// 是null直接返回了
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {// 不是工厂bean就抛出异常,虽然判断了&开头,也有可能不是
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean<?> factoryBean)) {// 不是FactoryBean直接返回
return beanInstance;
}
// 上面其实是做是不是FactoryBean的校验
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
object = getCachedObjectForFactoryBean(beanName);// 从缓存里面拿这个FactoryBean实例
}
if (object == null) {// 缓存没有就创建
// Return bean instance from factory.
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);// 合并BeanDefinition
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 就是获取FactoryBean的getObject方法返回值T对象,T对象是真正需要实例化的
object = getObjectFromFactoryBean(factoryBean, beanName, !synthetic);// 实例化-》断点进入11
}
return object;
}
我们看下object = getObjectFromFactoryBean(factoryBean, beanName, !synthetic);// 实例化-》断点进入11
该方法也是实例化的一个核心方法,有必要好好看下
断点进入来到了FactoryBeanRegistrySupport类里面
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {// 是单例并且包含名字
// 线程安全加锁了。因为FactoryBean本身默认是懒加载方式,Spring默认也是只初始化FactoryBean本身,如果多个Controller要获取这个FactoryBean的getObject方法返回值T对象,就会有线程安全问题。
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);// 缓存里面先取一次
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);// 本质就是调用FactoryBean的getObject方法,获取方法返回值T对象
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
上面代码看完后,我们回到getBean(beanName),再次断点进入
sharedInstance = getSingleton(beanName, () -> {// 断点进入2
该方法主要是存放到缓存中
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {// 多线程的取,所以得加锁
// 三级缓存:
// singletonObjects,一级缓存,存储的是所有创建好了的单例Bean(A的完全态实例)
// earlySingletonObjects,二级缓存,完成实例化,但是还未进行属性注入及初始化的对象(A非完全态实例)
// singletonFactories,三级缓存,提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象(A的单例工厂,获取的也是A自己的代理对象)
Object singletonObject = this.singletonObjects.get(beanName);// 一级缓存,成员变量,就是个Map,key是beanname,value是bean
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);// 创建前标记一下,表示要创建了
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
singletonObject = singletonFactory.getObject();// 获取bean,就是外面Lambda表达式createBean获取的bean
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);// 有异常,再从缓存取一次
if (singletonObject == null) {// 还是取不到就抛异常
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);// 创建后删除标记
}
if (newSingleton) {
addSingleton(beanName, singletonObject);// 将这个bean做缓存【循环依赖解决核心:存放到三个缓存逻辑】
}
}
return singletonObject;
}
}
我们继续回到getBean(beanName),再次断点进入
return createBean(beanName, mbd, args);// 真正核心-》断点进入X
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);// 解析出bean的Class
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);// 克隆了一个副本,不动原来的mbd,局部变量天生具备线程安全的特性,spring很多地方使用了克隆副本,改变副本这种处理方式
mbdToUse.setBeanClass(resolvedClass);// 副本设置一下beanClass属性
}
// 代理相关,将类里面的方法做替换,直接生成代理,一般情况用不到,这里代理也没有生成实例,所以不是常用代理。这边功能程序员极少接触到。
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();// 代理相关1
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);// 代理相关2
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);// 真正核心-》断点进入Y
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
我们断点进入
Object beanInstance = doCreateBean(beanName, mbdToUse, args);// 真正核心-》断点进入Y
【核心方法】
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// bean一共:1、bean实例化 2、bean属性填充 3、bean初始化
// 1、bean实例化
// Instantiate the bean.
BeanWrapper instanceWrapper = null;// BeanWrapper 将bean包装一下,是个工具类,更容易做反射处理,属性填充
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();// bean实例化了,mbd有Class等属性,利用反射无参构造方式newInstance实例出来。相当于一个对象new出来了,但是属性还没有填充,非完全态。
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
// 容许bean后置处理器对合并后的BeanDefinition做处理
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.markAsPostProcessed();
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 三级缓存:
// singletonObjects,一级缓存,存储的是所有创建好了的单例Bean(A的完全态实例)
// earlySingletonObjects,二级缓存,完成实例化,但是还未进行属性注入及初始化的对象(A非完全态实例)
// singletonFactories,三级缓存,提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象(A的单例工厂,获取的也是A自己的代理对象)
// bean提早暴露,这里是解决循环引用问题【循环依赖解决核心:提前暴露逻辑】
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&// 是单例 && 允许循环引用的配置开启,默认是关闭的,SpringBoot默认不支持,需要yml的地方配置allowCircularReferences 这个属性为true && 该单例正在被创建
isSingletonCurrentlyInCreation(beanName));// 单例正在被创建(就是有标记的那种)
if (earlySingletonExposure) {// 符合上面情况,就立马提前暴露
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 添加一个单例工厂,这里面其实就用到了三级缓存那几个map,如果有代理,就生成代理bean,没有代理就返回原生bean,是以工厂的形式暴露出去的
// getEarlyBeanReference,如果有代理,就生成代理bean,没有代理就返回原生bean
// addSingletonFactory,判断1级缓存是否包含beanName,不包含的情况下将上面的原生bean或者代理bean从二级缓存移除,放到了singletonFactories三级缓存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));// 断点进入-》三级缓存2-》断点进入getEarlyBeanReference-》断点进入getEarlyBeanReference
}
// Initialize the bean instance.
Object exposedObject = bean;// bean只是实例化的原生bean,还没有填充属性和初始化,是非完全态
try {
// 2、bean属性填充
populateBean(beanName, mbd, instanceWrapper);// 断点进入X1
// 3、bean初始化
// exposedObject 可以认为是完全态了,是初始化后的bean,如果程序员在bean后置处理器加了一些代码,可能导致初始化后的bean内存地址和最早的实例化bean内存地址不一样。比如代理,所以这边返回的exposedObject可能是内存地址不一样的代理bean,也可能是内存地址一样的原生bean。
exposedObject = initializeBean(beanName, exposedObject, mbd);// 断点进入X2
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
throw bce;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
}
}
// 【循环依赖解决核心:循环依赖初始化后处理逻辑】
if (earlySingletonExposure) {// 允许循环依赖配置开启
Object earlySingletonReference = getSingleton(beanName, false);// fasle只能是从一级或者二级缓存获取bean
if (earlySingletonReference != null) {// 如果有
if (exposedObject == bean) {// 初始化后的bean内存地址 == 最早实例化的原生bean
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
// 将bean注册为一次性的,判断bean在容器关闭的时候是否销毁
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
我们在doCreateBean的基础上断点进入
populateBean(beanName, mbd, instanceWrapper);// 断点进入X1
填充属性的方法
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
if (bw.getWrappedClass().isRecord()) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to a record");
}
else {
// Skip property population phase for records since they are immutable.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 判断bean后置处理是否有InstantiationAwareBeanPostProcessors接口,spring的灵活
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {// 实例化后回调方法,可以拿到实例化好但是没有填充属性的bean,来进行一些处理
return;
}
}
}
// 定义一个PropertyValues属性对象,这个是表示bean实例的所有属性对应的对象,后面就是各种方式处理属性,来构建这个属性对象。
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// 克隆副本
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);// byName的方式进行属性的自动装配(循环遍历bean的成员变量,如果需要这个成员变量,就getBean这个成员变量,并将这个成员变量注册成可依赖的bean,getBean的时候就是新的一轮了。)
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);// byType的方式进行属性的自动装配
}
pvs = newPvs;// 这样属性对象就准备好了
}
// bean的后置处理器,spring的灵活,可以对属性对象刚准备好的时候,再次对属性对象做一些处理。
if (hasInstantiationAwareBeanPostProcessors()) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
pvs = pvsToUse;
}
}
// 做一些依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
if (needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);// 真正的填充属性,主要是给bw设置了,然后里面一些属性是否需要转化等操作。
}
}
我们在doCreateBean的基础上断点进入
exposedObject = initializeBean(beanName, exposedObject, mbd);// 断点进入X2
bean的初始化
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
invokeAwareMethods(beanName, bean);// 优先处理Aware相关标识的bean
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 调用所有bean后置处理器,初始化前的方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);// 真正初始化
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 调用所有bean后置处理器,初始化后的方法,这边可能产生代理,返回的wrappedBean 可能是原生bean,也可能是代理。(如果允许循环依赖配置开启了,三级缓存那边生成代理bean了,这边就不会再重复生成代理bean了)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
下面说下三级缓存
我们在doCreateBean的基础上断点进入
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));// 断点进入-》三级缓存2-》断点进入getEarlyBeanReference-》断点进入getEarlyBeanReference
主要是三级缓存相关内容
先看后面的getEarlyBeanReference方法(该方法先执行,后才执行addSingletonFactory),该方法主要是有代理就生成代理bean,没有就返回原始bean。
// bean是反射newInstance出来的bean,还没有进行属性填充和初始化
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);// 断点进入到下面抽象类AbstractAutoProxyCreator的getEarlyBeanReference方法中
}
}
return exposedObject;
}
// 抽象类AbstractAutoProxyCreator的getEarlyBeanReference方法,由上面断点进入
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);// class和beanName联合生成一个key
this.earlyProxyReferences.put(cacheKey, bean);// 非完全态的bean放到二级缓存中
return wrapIfNecessary(bean, beanName, cacheKey);// 如果有必要进行包装,这里本质就是有代理,就生成代理bean了,没有代理就返回原生bean。
}
我们看前面的addSingletonFactory方法,该方法主要是添加单例工厂
// 上面getEarlyBeanReference返回的是原始bean或者代理bean,这边方法参数传入的是个ObjectFactory接口,该接口getObject方法返回的T对象就是上面getEarlyBeanReference返回的是原始bean或者代理bean,有点类似FactoryBean,这里是单例工厂。
// 该方法添加单例工厂到三级缓存中,将来通过beanName可以从三级缓存中取出ObjectFactory,这个ObjectFactory就有返回T对象的能力,而返回的T对象可以是原始bean也可以是代理bean。这是Spring代理工厂设计模式,个人感觉多个地方使用的时候可以隐藏这种返回原生还是代理的逻辑,节约代码(不用每次都去判断,工厂直接拿),方便好用。
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {// 判断一级缓存不包含beanName
this.singletonFactories.put(beanName, singletonFactory);// 放到了三级缓存中
this.earlySingletonObjects.remove(beanName);// 原生bean或者代理bean从二级缓存移除
this.registeredSingletons.add(beanName);
}
}
}
上面代码看完后,我们回到最早的getBean(beanName),在getBean(beanName)的基础上,再次断点进入
Object sharedInstance = getSingleton(beanName);// 断点进入-》三级缓存1
主要是三级缓存解决循环依赖详细解析
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
// 我们假设一种循环依赖的场景,A依赖B,B依赖A,A和B都没有代理,允许循环依赖配置开启,每一个bean的创建需要三步:1、实例化 2、填充属性 3、初始化
// 但是每一个getBean需要多步:1、先beanName从三个级别缓存里面取bean 2、取到直接用,取不到就触发bean的创建三步。
// 一级缓存(A、B等bean的完全态,实例化到初始化都做完了,完全态的bean在二级、三级缓存中一般没有,只在一级缓存)
// 二级缓存(A、B等bean的非完全态,只实例化)
// 三级缓存(A、B等bean的单例工厂,之所以用工厂,是因为工厂可能返回A,可能返回A的代理,更符合实际要求,都是非完全态,提前暴露的bean都是暴露bean对应单例工厂,所以在一级、二级缓存中一般没有,只在三级缓存)
// getBean简单流程:getBean开始-》三个缓存中获取bean,有就getBean完成,没有就走后面逻辑-》bean实例化-》bean提前暴露-》bean填充属性-》bean初始化-》循环依赖初始化后处理逻辑-》存放到三个缓存逻辑-》getBean完成
// 坑1:这里说的所有的代理bean,都是指Spring官方的默认代理bean,比如bean单例工厂可能返回A,也可能返回A的代理,是指没有程序员额外加过代码的。
// 坑2:bean初始化这一步的时候,bean后置处理器是可以被程序员强行干涉加代码的,比如给bean A初始化的时候,在bean后置处理器new 一个新的A,此时A初始化以后已经不是原来内存地址的A了,完全是一个全新的A。
// 【循环依赖解决核心:从三个缓存获取逻辑】:先从一级、然后再二级、最后三级取,如果触发了从第三级取,则会从一级缓存里面删除,放到二级缓存里面。
// 【循环依赖解决核心:提前暴露逻辑】:在实例化后面并且在填充属性逻辑前,有个提前暴露逻辑,需要允许循环依赖配置开启,才会触发,主要逻辑就是从二级缓存移除bean,将bean对应的单例工厂放到三级缓存中。
// 【循环依赖解决核心:循环依赖初始化后处理逻辑】:【难点】需要允许循环依赖配置开启,才会触发,只从一二缓存级中获取bean,没获取到则什么都不做,返回初始化后的bean,如获取到以后,对比初始化后的bean和最早只实例化的bean的内存地址是否相等,如果相等将从一二级缓存中获取的bean返回给getBean,如果不相等则再通过一些判断会抛出异常。内存地址不相等情况见上面坑2,坑2基本会导致抛异常。所以这边返回的bean有三种情况:初始化后的bean、一二级缓存中获取的原生bean(因为同一个地址指向,是完全态的原生bean)、一二级缓存中获取的代理bean(代理bean一直没有被填充属性和初始化,是非完全态的bean,这导致代理bean里面的循环依赖属性是null)。
// 【循环依赖解决核心:存放到三个缓存逻辑】:放到一级缓存中,从二级、三级缓存中删除。
// 下面为三级缓存解决循环依赖具体流程:
// 1、首先A的getBean,最开始的时候,缓存肯定没有(【循环依赖解决核心:从三个缓存获取逻辑】),触发A的bean创建三步;
// 2、然后bean创建三步_A第一步反射newInstance进行实例化,实例化后,如果允许循环依赖配置开启,就将A提前暴露,A的单例工厂放到三级缓存中(【循环依赖解决核心:提前暴露逻辑】);
// 3、然后bean创建三步_A第二步填充,填充的时候发现需要依赖B,在填充逻辑里面,会触发B的getBean方法,这样就得走B的getBean;
// 4、然后B的getBean,最开始的时候,缓存肯定没有,触发B的bean创建三步;
// 5、然后bean创建三步_B第一步反射newInstance进行实例化,实例化后,如果允许循环依赖配置开启,就将B提前暴露,B的单例工厂放到三级缓存中;
// 6、然后bean创建三步_B第二步填充,填充的时候发现需要依赖A,在填充逻辑里面,会触发A的getBean方法,这样就得走A的getBean;
// 7、然后A的getBean,已经不是最开始了,缓存已经有了,A是提前暴露过的,可以在三级缓存取到A对应的单例工厂,然后A的单例工厂可以获取到A或者A的代理,这个时候三级缓存会将A对应的单例工厂删除,并且A或者A的代理也进入到二级缓存了(思考:如果是A的代理放到二级缓存,原始A理论上在二级缓存应该是没有的,工厂最终放的也是A的代理,不过原始A是一路创建出来到初始化完成的)。
// 8、然后bean创建三步_B第二步填充可以拿到A或者代理A,并且顺利完成B的填充,此时B已经有了A或者代理A这个属性;
// 9、然后bean创建三步_B第三步初始化;
// 10、然后如果允许循环依赖配置开启,B的循环依赖初始化后处理逻辑开始,此时B还没有放到任何一级缓存中,所以该逻辑什么都没做(【循环依赖解决核心:循环依赖初始化后处理逻辑】);
// 11、然后B存放到三个缓存逻辑开始,将B放到一级缓存中,从二、三级缓存中删除,B之前在第5步提前暴露过,所以三级缓存有B的单例工厂,在这步也将该单例工厂删除了,完全态的B此时只在一级缓存中了,二三级没有B的任何身影【循环依赖解决核心:存放到三个缓存逻辑】;
// 12、然后整个B的getBean完成了,导致A的填充可以拿到B了,并且顺利完成A的填充,此时A已经有了B这个属性;
// 13、然后bean创建三步_A第三步初始化,这里特别注意,哪怕第7步二级缓存存的是A的代理,这边初始化后得到的仍然是原始A;
// 14、然后如果允许循环依赖配置开启,A的循环依赖初始化后处理逻辑开始,A或者A的代理之前在第6步被放到了二级缓存,可以从二级缓存获取到bean,对比初始化后的A和最早只实例化的A的内存地址是否相等,不考虑坑2的情况下,内存地址一般相等,则将二级缓存获取的完全态的A或者非完全态的代理A返回给A的getBean,在我们大前提A和B都没有代理的情况下,这儿返回的就是完全态的A给A的getBean(难点:原生A在第12步的时候已经有了B属性了,在第13步也初始化了,而且13步返回的仍然是原生A,因为原生A在不考虑坑2的情况下自始至终内存地址没变过,所以二级缓存再去获取,反而拿到了完全态的A了,二级缓存只放非完全态的bean概念其实也就不对了,而代理A是新的内存地址,一直没机会做填充和初始化,在14步这边返回的就是非完全态的代理A了);
// 15、然后A存放到三个缓存逻辑开始,将A放到一级缓存中,A之前在第7步的时候进入到二级缓存,此时也从二、三级缓存中删除,A此时只在一级缓存中了,二三级没有A的任何身影;
// 16、这样A的getBean就完成了。
// 注意:三级缓存是针对单例来说的,是单例才去缓存的,非单例整个逻辑都是不缓存的,涉及不到三级缓存。
// 允许循环依赖配置默认不开启,有任何循环依赖,都会启动报错,开启了则分下面几种情况:
// A依赖B,B依赖A,A和B都没有代理,结果:A(B)、B(A) 启动正常,依赖正常,完全态的A和B
// A依赖B,B依赖A,A有代理(简称AP,A不等于AP),B没有代理,结果:A(B)、B(AP)、AP(null) 启动正常依赖不正常,容器里面是AP和B,业务逻辑代码开发用AP的时候,getB属性的时候,是null,容易引起业务代码错误。
// A依赖B,B依赖A,A、B都有代理,结果:AP(null)、BP(null)启动正常,依赖全部不正常,容器里面是AP和BP,业务逻辑代码开发用的是AP和BP,get属性的时候,都是null,容易引起业务代码错误。
// 当有代理的时候,我们业务逻辑使用的时候,都是用的代理,比如上面业务代码用的AP、BP而非用A、B,所以代理会打破循环依赖,让循环依赖彻底失效。有代理的情况下最好是引入C,来将A和B关联起来,从根上避免循环依赖,这也是Spring官方给的建议。
// 我结合IT楠哥视频,debug验证研究了三四天,非常精确并正确的三级缓存解决循环依赖的分析。
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);// 从一级缓存取,没上锁
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);// 从二级缓存取,没上锁
if (singletonObject == null && allowEarlyReference) {// allowEarlyReference是false,下面的就不执行
synchronized (this.singletonObjects) {// 上锁
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);// 再从一级缓存取,上锁了,多线程,这样写健壮
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);// 从二级缓存取
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);// 从三级缓存取,取出单例工厂
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();// 单例工厂取出对象T,这个T可能是代理,可能是原生bean,看这里面就隐藏了实现类的具体逻辑,其实实现类就是() -> getEarlyBeanReference(beanName, mbd, bean),我们之前看的断点,Lambda表达式里面的逻辑就是实现类逻辑。
this.earlySingletonObjects.put(beanName, singletonObject);// 放到二级缓存中
this.singletonFactories.remove(beanName);// 从三级缓存移除
}
}
}
}
}
}
return singletonObject;// 可能为null
}
三级缓存解决循环依赖原理图
小总结一下getBean:
12、finishRefresh(完成刷新)
最后刷新容器发布刷新事件(Spring cloud eureka 也是从这里启动的),refresh做完之后需要做的其他事情。
- 初始化生命周期处理器,并设置到Spring容器中(LifecycleProcessor)
- 调用生命周期处理器的onRefresh方法,这个方法会找出Spring容器中实现了SmartLifecycle接口的类并进行start方法的调用
- 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor(); // 初始化⽣命周期处理器-》断点进入1
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();// 调⽤⽣命周期处理器的onRefresh⽅法
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this)); // 发布ContextRefreshedEvent事件
}
初始化⽣命周期处理器-》断点进入1
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();// 获取beanFactory⼯⼚
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {// 判断容器中是否有lifecycleProcessor,有就直接从容器中拿
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {// 没有创建⼀个DefaultLifecycleProcessor,然后注册到容器中
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
如果是web容器ServletWebServerApplicationContext还会启动web服务和发布消息
protected void finishRefresh() {
super.finishRefresh();
WebServer webServer = startWebServer();
if (webServer != null) {
publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}
Spring小总结:
方法你来定义,我来调用(我指Spring,你指程序员);
程序员去new的话,会产生大量对象,导致频繁gc,容器去new,天然的单例,gc次数就少了;
提前创建bean的好处,提前暴露错误,如果运行的时候,new的时候报错就不好了;
统一的扩展处理,比如aop就只是一个扩展,可以做很多事情,比如事务、日志等;
依赖接口编程,依赖注入的时候,注入接口,容器来调用具体实现,实现解耦,完美解释多态;
参考资料:
Spring源码学习---------(最简单易懂的源码学习笔记)
Spring源码解析-Spring IOC