比如通过反射实例化对象
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将调用该接口的初始化方法postProcessAfterInitialzation(),此时,Bean已经可以被应用系统使用了>
10.如果在<bean>中指定了该Bean的作用范围scope="singleton",则该Bean将放入Spring IOC的缓存池中,将触发Spring 对该Bean的生命周期管理;如果在<bean>中指定了该属性的作用范围scope="prototype",则将该Bean交给调用者
11.如果Bean实现了DisposableBean接口,则Spring会调用destory()方法将Spring中的Bean销毁;如果在配置文件中通过destory-method属性指定了Bean的销毁方法,则Spring将调用该方法对Bean进行销毁
<注意:Spring为Bean提供了细致全面的生命周期过程,通过实现特定的接口或bean的属性值设置,都可以对Bean的生命周期过程产生影响,虽然可以随意配置bean的属性值,但是建议不要过多的使用Bean实现接口,因为这样会导致代码和Spring的聚合过于紧密>
import org.springframework.beans.factory.InitializingBean;
public class LagouBean implements InitializingBean {
private Integer id;
private String message;
public LagouBean() {
System.out.println("构造函数...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化....");
}
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* @Author 应癫
* @create 2019/12/3 16:59
*/
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;
}
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* @Author 应癫
* @create 2019/12/3 16:56
*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
System.out.println("BeanFactoryPostProcessor的实现类构造函数...");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessor的实现方法调用中......");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
">
<bean id="lagouBean" class="LagouBean"></bean>
<bean id="myBeanFactoryPostProcessor" class="MyBeanFactoryPostProcessor"/>
<bean id="myBeanPostProcessor" class="MyBeanPostProcessor"/>
</beans>
@Test
public void testGetBean(){
// ApplicationContext是容器的高级接口,BeanFactory(顶级容器/根容器,规范了/定义了容器的基础行为)
// 叫做单例池,singletonObjects,容器是一组组件和过程的集合,包括BeanFactory、单例池、BeanPostProcessor等以及之间的协作流程)
// 反向观察bean的调用,通过debug查看调用栈
// bean对象的构造方法、初始化方法、 bean后置处理器before/after方法: org.springframework.context.support.AbstractApplicationContext#refresh#finishBeanFactoryInitialization
// beanFactory后置处理器构造方法、postProcessBeanFactory方法:org.springframework.context.support.AbstractApplicationContext#refresh#invokeBeanFactoryPostProcessors
// bean后置处理器构造方法: org.springframework.context.support.AbstractApplicationContext#refresh#registerBeanPostProcessors
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
LagouBean lagouBean = (LagouBean) applicationContext.getBean("lagouBean");
System.out.println(lagouBean);
}
(1) 分析 Bean 的创建是在容器初始化时还是在 getBean 时
所以:未设置延迟加载的前提下,Bean 的创建是在容器初始化过程中完成的
(2)分析构造函数调⽤情况
通过如上观察,我们发现构造函数的调⽤时机在AbstractApplicationContext类refresh⽅法的
finishBeanFactoryInitialization(beanFactory)处;
(3)分析 InitializingBean 之 afterPropertiesSet 初始化⽅法调⽤情况观察
InitializingBean中afterPropertiesSet ⽅法的调⽤时机也是在AbstractApplicationContext类refresh⽅法的finishBeanFactoryInitialization(beanFactory);
(4)分析BeanFactoryPostProcessor 初始化和调⽤情况
分别在构造函数、postProcessBeanFactory ⽅法处打断点,观察调⽤栈,发现
BeanFactoryPostProcessor 初始化在AbstractApplicationContext类refresh⽅法的
invokeBeanFactoryPostProcessors(beanFactory);
postProcessBeanFactory 调用在AbstractApplicationContext类refresh⽅法的
invokeBeanFactoryPostProcessors(beanFactory);
(5)分析 BeanPostProcessor 初始化和调⽤情况
分别在构造函数、postProcessBeanFactory ⽅法处打断点,观察调⽤栈,发现
BeanPostProcessor 初始化在AbstractApplicationContext类refresh⽅法的
registerBeanPostProcessors(beanFactory);
postProcessBeforeInitialization 调用在AbstractApplicationContext类refresh⽅法的
finishBeanFactoryInitialization(beanFactory);
postProcessAfterInitialization 调用在AbstractApplicationContext类refresh⽅法的
finishBeanFactoryInitialization(beanFactory);
总结
根据上⾯的调试分析,我们发现 Bean对象创建的⼏个关键时机点代码层级的调⽤都在AbstractApplicationContext 类 的 refresh ⽅法中,可⻅这个⽅法对于Spring IoC 容器初始化来说相当关键,汇总如下:
关键点 | 触发代码 |
---|---|
构造器 | refresh#finishBeanFactoryInitialization(beanFactory) |
BeanFactoryPostProcessor 初始化 | refresh#invokeBeanFactoryPostProcessors(beanFactory) |
BeanFactoryPostProcessor ⽅法调用 | refresh#invokeBeanFactoryPostProcessors(beanFactory) |
BeanPostProcessor 初始化 | registerBeanPostProcessors(beanFactory) |
BeanPostProcessor ⽅法调⽤ | refresh#finishBeanFactoryInitialization(beanFactory) |
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
/*第一步:刷新前的预处理
表示在真正做refresh操作之前需要准备做的事情;
设置Spring容器的启动时间
开启活跃状态、撤销关闭状态
验证环境信息里一些必须存在的属性等
*/
prepareRefresh();
/* 第二步:Tell the subclass to refresh the internal bean factory.
获取BeanFactory;默认实现是DefaultListableFactory
加载BeanDefition 并注册到 BeanDefitionRegistry
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 第三步:BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器等)
prepareBeanFactory(beanFactory);
try {
// 第四步:BeanFactory准备⼯作完成后进⾏的后置处理⼯作
postProcessBeanFactory(beanFactory);
// 第五步:实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// 第六步:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执
registerBeanPostProcessors(beanFactory);
// 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
initMessageSource();
// 第⼋步:初始化事件派发器
initApplicationEventMulticaster();
// 第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
onRefresh();
// 第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean
registerListeners();
/*
第⼗⼀步:
初始化所有剩下的⾮懒加载的单例bean
初始化创建⾮懒加载⽅式的单例Bean实例(未设置属性)
填充属性
初始化⽅法调⽤(⽐如调⽤afterPropertiesSet⽅法、init-method⽅法)
调⽤BeanPostProcessor(后置处理器)对实例bean进⾏后置处
*/
finishBeanFactoryInitialization(beanFactory);
/*
第⼗⼆步:
完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,并且发布事
件 (ContextRefreshedEvent)
*/
finishRefresh();
}
...
}
}
Step 1:⼦流程⼊⼝在 AbstractRefreshableApplicationContext#refreshBeanFactory ⽅法中
Step 2:依次调⽤多个类的 loadBeanDefinitions ⽅法 —> AbstractXmlApplicationContext —>AbstractBeanDefinitionReader —> XmlBeanDefinitionReader ⼀直执⾏到XmlBeanDefinitionReader 的 doLoadBeanDefinitions ⽅法
Step 3:我们重点观察XmlBeanDefinitionReader 类的 registerBeanDefinitions ⽅法,期间产⽣了多次重载调⽤,我们定位到最后⼀个
此处我们关注两个地⽅:⼀个createRederContext⽅法,⼀个是DefaultBeanDefinitionDocumentReader类的registerBeanDefinitions⽅法,先进⼊createRederContext ⽅法看看
我们可以看到,此处 Spring ⾸先完成了 NamespaceHandlerResolver 的初始化。
我们再进⼊ registerBeanDefinitions ⽅法中追踪,调⽤了
DefaultBeanDefinitionDocumentReader#registerBeanDefinitions ⽅法
进⼊ doRegisterBeanDefinitions ⽅法
进⼊ parseBeanDefinitions ⽅法
进⼊ parseDefaultElement ⽅法
进⼊ processBeanDefinition ⽅法
⾄此,注册流程结束,我们发现,所谓的注册就是把封装的 XML 中定义的 Bean信息封装为BeanDefinition 对象之后放⼊⼀个Map中,BeanFactory 是以 Map 的结构组织这些 BeanDefinition的。
可以在DefaultListableBeanFactory中看到此Map的定义
private final Map
@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);
// 触发所有非懒加载单例bean初始化
for (String beanName : beanNames) {
// 获取bean定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判断是否是懒加载bean,如果是单例的并且不是懒加载的则在容器创建时初始化
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 判断是否是FactoryBean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
/**
*如果是普通bean则进⾏初始化并依赖注⼊,此 getBean(beanName)接下来触发的逻辑
* 和懒加载时 context.getBean("beanName") 所触发的逻辑是⼀样的
*/
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
注意,这⾥不是函数的循环调⽤,是对象的相互依赖关系。循环调⽤其实就是⼀个死循环,除⾮有终结条件。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
在获取bean之前如果这个原型bean正在被创建则直接抛出异常。原型bean在创建之前会进⾏标记这个beanName正在被创建,等创建结束之后会删除标记
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
总结:Spring 不⽀持原型 bean 的循环依赖。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
阅读源码一定要抓主线,不能掉进某一行代码当中陷进去。以具体实例断点调试步步分析。
文章内容输出来源:拉勾教育Java高薪训练营