看源码
- 好处:提高培养代码架构思维、深入理解框架
- 原则
- 定焦原则:抓主线,比如BeanFactory的创建流程、Bean对象创建流程、lazy-int延迟加载流程、SpringIoc循环依赖原理,其他的不关心
- 宏观原则:站在上帝视角,关注源码结构和业务流程(淡化具体某行代码的编写细节),不需要扣太细,不然读不下去
- 读源码的方法和技巧
- 断点(观察调用栈)
- 反调(Find Usages),不知道改方法在哪个地方被调用了,右键find Usages
- 经验(spring框架中doXXX,做具体处理的地方)
- Spring源码构建
- 下载源码(github)
- 安装gradle 5.6.3(类似于maven) Idea 2019.1 Jdk 11.0.5
- 导入(耗费一定时间)
- 编译工程(顺序:core-oxm-context-beans-aspects-aop)工程—>tasks—>compileTestJava
一、Spring IoC容器初始化主体流程
1.1、Spring IoC的容器体系
IoC容器是Spring的核心模块,是抽象了对象管理、依赖关系管理的框架解决方案。Spring 提供了很多的容器,其中 BeanFactory 是顶层容器(根容器),不能被实例化,它定义了所有 IoC 容器必须遵从的一套原则,具体的容器实现可以增加额外的功能,比如我们常用到的ApplicationContext,其下更具体的实现如 ClassPathXmlApplicationContext 包含了解析 xml 等一系列的内容,AnnotationConfigApplicationContext 则是包含了注解解析等一系列的内容。Spring IoC 容器继承体系非常聪明,需要使用哪个层次用哪个层次即可,不必使用功能大而全的。
ApplicationContext是容器的高级接口,BeanFacotry(顶级容器/根容器,规范了/定义了容器的基础行为)
Spring应用上下文,官方称之为 IoC容器(错误的认识:容器就是map而已;准确来说,map是ioc容器的一个成员, 叫做单例池,singletonObjects。容器是一组组件和过程的集合,包括BeanFactory、单例池、BeanPostProcessor等以及之间的协作流程)
![](https://i-blog.csdnimg.cn/blog_migrate/f9582c8f9e50f1b471b3f19172841597.png)
1.2、Bean生命周期关键时机点
package com.lagou.edu;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class LagouBean implements InitializingBean, ApplicationContextAware {
/*private ItBean itBean;
public void setItBean(ItBean itBean) {
this.itBean = itBean;
}*/
private int num;
public void setNum(int num) {
this.num = num;
}
/**
* 构造函数
*/
public LagouBean(){
System.out.println("LagouBean 构造器...");
}
/**
* InitializingBean 接口实现
*/
public void afterPropertiesSet() throws Exception {
System.out.println("LagouBean InitializingBean#afterPropertiesSet...");
}
public void print() {
System.out.println("print方法业务逻辑执行");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("setApplicationContext....");
}
/**
* BeanFactoryPostProcessor的实现类构造函数...
* BeanFactoryPostProcessor的实现方法调用中......
* BeanPostProcessor 实现类构造函数...
* LagouBean 构造器...
* setApplicationContext....
* BeanPostProcessor 实现类 postProcessBeforeInitialization 方法被调用中......
* LagouBean afterPropertiesSet...
* BeanPostProcessor 实现类 postProcessAfterInitialization 方法被调用中......
* com.lagou.edu.LagouBean@6ad3381f
*/
}
package com.lagou.edu;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
System.out.println("BeanPostProcessor 实现类构造函数...");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("lagouBean".equals(beanName)) {
System.out.println("BeanPostProcessor 实现类 postProcessBeforeInitialization 方法被调用中......");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("lagouBean".equals(beanName)) {
System.out.println("BeanPostProcessor 实现类 postProcessAfterInitialization 方法被调用中......");
}
return bean;
}
}
BeanFactoryPostProcessor接口实现类
package com.lagou.edu;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
System.out.println("BeanFactoryPostProcessor的实现类构造函数...");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessor的实现方法调用中......");
}
}
import com.lagou.edu.LagouBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class IocTest {
/**
* Ioc 容器源码分析基础案例
*/
@Test
public void testIoC() {
// ApplicationContext是容器的高级接口,BeanFacotry(顶级容器/根容器,规范了/定义了容器的基础行为)
// Spring应用上下文,官方称之为 IoC容器(错误的认识:容器就是map而已;准确来说,map是ioc容器的一个成员,
// 叫做单例池, singletonObjects,容器是一组组件和过程的集合,包括BeanFactory、单例池、BeanPostProcessor等以及之间的协作流程)
/**
* Ioc容器创建管理Bean对象的,Spring Bean是有生命周期的,在特殊方法打断点可知
* bean构造函数执行、初始化方法执行 、Bean后置处理器的before/after方法:AbstractApplicationContext#refresh()#finishBeanFactoryInitialization()
*
* Bean工厂后置处理器构造函数执行、Bean工厂后置处理器方法执行:AbstractApplicationContext#refresh()#invokeBeanFactoryPostProcessors()
*
* Bean后置处理器构造函数执行:AbstractApplicationContext#refresh()#registerBeanPostProcessors()
*/
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
System.out.println(lagouBean);
}
}
1.3、Spring IoC容器初始化主流程
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
/**
* 第⼀步:刷新前的预处理
* 表示在真正刷新之前需要准备做的事情:
* 设置sping容器的启动时间
* 开启活跃状态,撤销关闭状态
* 验证环境信息里一些必要的属性
*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/**
* 第⼆步:获取BeanFactory,有了bean工厂才能创建bean,默认实现是DefaultListableBeanFactory
* 读取配置文件信息,将<bean></bean>中的信息封装成BeanDefition 并注册到 BeanDefitionRegistry(是一个map)
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 第三步:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 第四步:BeanFactory准备⼯作完成后进⾏的后置处理⼯作
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 第五步: 实例化并调用实现了BeanFactoryPostProcessor接口的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 第六步:注册BeanPostProcessors(Bean的后置处理器)
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
initMessageSource();
// Initialize event multicaster for this context.
// 第八步:初始化事件分发器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
onRefresh();
// Check for listener beans and register them.
// 第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
/**
* 第十一步:
* 初始化所有剩下的非懒加载的单例bean
* 初始化创建非懒加载方式的单例bean实例(未设置属性)
* 填充属性
* 初始化方法调用,(比如调用afterPropertiesSet方法、init-method方法)
* 调用BeanPostProcessor(bean后置处理器)对实例bean进行后处置
*/
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 第⼗⼆步:完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事 (ContextRefreshedEvent)
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
二、BeanFactory创建流程
2.1 获取beanFactory子流程
![](https://i-blog.csdnimg.cn/blog_migrate/bab44db1c4d95fe5916bf5585e66d1aa.png)
2.2、BeanDefinition加载解析及注册子流程
![](https://i-blog.csdnimg.cn/blog_migrate/de8b263c91b4a5315bfe617ff8d140b3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/03b28dd4d55c4e4cf3405cbee1f714e6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/79e2fe51792b88da2470b47f0b3f8b5f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d675a2d776d3c04ce706db3336b1dca2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6494b3c063a260ea1b0f5d1a815cb37f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b31bc7a69e148147360f6a48714a9c02.png)
![](https://i-blog.csdnimg.cn/blog_migrate/93b8084496cbc0adcadb47ecb2bb7956.png)
![](https://i-blog.csdnimg.cn/blog_migrate/dd8a16544eafab6c5df52b9671122d12.png)
![](https://i-blog.csdnimg.cn/blog_migrate/848b1991cf589db9c639d803cca04afe.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c71fed108d7f1050fcc30f03af713f04.png)
![](https://i-blog.csdnimg.cn/blog_migrate/828c3e676b19c1f9c1406b885698227b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/52e18e153d24bec671de6ce3aad6447b.png)
三、Bean创建流程
Bean ⽣命周期的整个执⾏过程描述:
1)根据配置情况调⽤ Bean 构造⽅法或⼯⼚⽅法实例化 Bean。
2)利⽤依赖注⼊完成 Bean 中所有属性值的配置注⼊。
3)如果 Bean 实现了 BeanNameAware 接⼝,则 Spring 调⽤ Bean 的 setBeanName() ⽅法传⼊当前 Bean 的 id 值。
4)如果 Bean 实现了 BeanFactoryAware 接⼝,则 Spring 调⽤ setBeanFactory() ⽅法传⼊当前⼯⼚实例的引⽤。
5)如果 Bean 实现了 ApplicationContextAware 接⼝,则 Spring 调⽤ setApplicationContext() ⽅法传⼊当前 ApplicationContext 实例的引⽤。
6)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调⽤该接⼝的预初始化⽅法postProcessBeforeInitialzation() 对 Bean 进⾏加⼯操作,此处⾮常重要,Spring 的 AOP 就是利⽤它实现的。
7)如果 Bean 实现了 InitializingBean 接⼝,则 Spring 将调⽤ afterPropertiesSet() ⽅法。
8)如果在配置⽂件中通过 init-method 属性指定了初始化⽅法,则调⽤该初始化⽅法。
9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调⽤该接⼝的初始化⽅法 postProcessAfterInitialization()。
此时,Bean 已经可以被应⽤系统使⽤了。
10)如果在 <bean> 中指定了该 Bean 的作⽤范围为 scope="singleton",则将该 Bean 放⼊ Spring IoC 的缓存池中,
将触发 Spring 对该 Bean 的⽣命周期管理;如果在 <bean> 中指定了该 Bean 的作⽤范围为 scope="prototype",则将该 Bean 交给调⽤者
11)如果 Bean 实现了 DisposableBean 接⼝,则 Spring 会调⽤ destory() ⽅法将 Spring 中的 Bean 销毁;
如果在配置⽂件中通过 destory-method 属性指定了 Bean 的销毁⽅法,则 Spring 将调⽤该⽅法对 Bean 进⾏销毁。
注意:Spring 为 Bean 提供了细致全⾯的⽣命周期过程,通过实现特定的接⼝或 <bean> 的属性设置,都可以对 Bean 的⽣命周期过程产⽣影虽然可以随意配置 <bean> 的属性,但是建议不要过多地使⽤ Bean 实现接⼝,因为这样会导致代码和 Spring 的聚合过于紧密
![](https://i-blog.csdnimg.cn/blog_migrate/369b3105509757072b2f5897ce5b3c7e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/810dbe500c73da020b7038093161d313.png)
![](https://i-blog.csdnimg.cn/blog_migrate/341b1d3dabbc32b2da670c720429852b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d5f05f940a7f8581c088d180cf7c82f1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/58aa25e5cc20969ad8bf693f47c94613.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6704c78f346a92bdee650c5af4f2577d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9260ac6ecffda5e5478f0d3c45f4760b.png)