Bean的生命周期:实例化->属性填充->初始化->销毁
核心入口方法:finishBeanFactoryInitialization-->preInstantiateSingletons
DefaultListableBeanFactory#preInstantiateSingletons用于实例化非懒加载的bean。
1.preInstantiateSingletons方法分析
作用:实例化非懒加载的bean
1.拿到所有BeanDefinitionName,遍历所有beanName
2.getMergedLocalBeanDefinition,将属性合并生成MergeBeanDefinition,如下图的属性
最终结果是:Map<beanName,RootBeanDefinition>,beanName对应合并后的BeanDefintion
如果存在父子BeanDefinition,则要合并,二合一会生成第三个BeanDefinition(新的);否则,就直接返回自己的BeanDefinition。
如果该BeanDefinition是RootBeanDefinition,就直接cloneBeanDefinition,并返回。
同时,涉及到递归合并,合并的父亲又有父亲beanDefinition,就需要多次合并。(这段源码的含义)
java
// 子BeanDefinition的属性覆盖父BeanDefinition的属性,这就是合并
mbd = new RootBeanDefinition(pbd);
mbd.overrideFrom(bd);
3.会判断是不是懒加载、是不是单例Bean、是不是抽象BeanDefinition,如果都不是,则进入步骤4
4.如果是FactoryBean,则开始创建FactoryBean。FactoryBean对应两个bean对象,但是只有一个beanDefinition。核心代码如下:
java
for (String beanName : beanNames) {
// 获取合并后的BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// isAbstract 抽象的BeanDefinition和抽象类无关
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
// 获取FactoryBean对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
// 判断是否打开了安全管理器
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
// 实现了接口SmartFactoryBean,并且isEagerInit=true
// 实现了接口FactoryBean,重写的getObject()方法 是在用户使用getBean的时候调用的
// SmartFactoryBean可以指定在 bean创建的时候 调用getObject()方法
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
// 创建真正的Bean对象(getObject()返回的对象)
getBean(beanName);
}
}
}
else {
// 创建Bean对象
getBean(beanName);
}
}
}
如果我们从单例池拿到了bean,那么就要判断是否和我们想要的bean类型一样(FactoryBean还是普通bean)。从Cache拿bean,getCachedObjectForFactoryBean(存放getObject生成的bean)
下面的代码:判断该bean是不是FactoryBean。
java
@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
String beanName = transformedBeanName(name);
Object beanInstance = getSingleton(beanName, false);
if (beanInstance != null) {
return (beanInstance instanceof FactoryBean);
}
// No singleton instance found -> check bean definition.
// 去父beanFactory找 是否有该beanName
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
}
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}
注意:如果FactoryBean类实现了SmartFactoryBean,并且重写了isEagerInit()方法,则在bean生命周期中就会创建FactoryBean,否则在getBean的时候才会创建FactoryBean。
5.不是FactoryBean且是非懒加载的bean
调用getBean,创建Bean
6.所有的非懒加载单例Bean都创建完了后,getSingleton(beanName);拿出所有单例Bean,看其是否实现了SmartInitializingSingleton接口,如果实现了这个接口,就执行重写后的方法:afterSingletonsInstantiated。
afterSingletonsInstantiated的调用时机:所有非懒加载的bean都创建完了之后,调用它
2.getBean
首先,getBean有三种调用方式:
name, name+type(验证类型,可类型转换),name+args[](args[]用于推断构造方法)
getBean的核心方法是doGetBean
1.transformedBeanName
拿到BeanName,transformedBeanName就是去掉&符号 ,以及将别名转换为主名。
示例1:@Bean({{"userService","userService1", "userService2"}):第一个名字是名字,后面的都是别名
示例2:&factoryBeanName是拿factoryBeanName;而factoryBeanName是拿getObject的bean。(比如UserBean)
2.getSingleton
先去单例池拿bean,拿到了就检查符不符合我们的需求(原型也走这一步)
3.拿不到,则进入else分支,创建bean
4.进入这行代码,parentBeanFactory != null && !containsBeanDefinition(beanName)
检查当前是否存在这个beanName的BeanDefinition,也要检查父BeanFactory有没有BeanDefinition,有就返回bean
5.核心开始,getMergedLocalBeanDefinition,拿到合并的BeanDefinition
6.checkMergedBeanDefinition
检查BeanDefinition是不是Abstract的,如果是,则不能创建bean(抽象的beanDefinition不能创建bean)
7.getDependsOn
处理@DepondsOn注解。检查依赖,将其挂载到该bean的依赖属性上,然后创建依赖的bean,如果创建失败,则会抛出异常。
存在一些依赖,就将依赖关系存入map(使用registerDependentBean方法),然后getBean(创建所依赖的bean,此时也会判断是否存在循环依赖的关系)
[比如类A上加了@DepondsOn("B"),则在创建A之前必须把B创建出来。如果类B也通过这种方式依赖了A,那么就产生了循环依赖,这种情况的循环依赖会直接抛出异常,无法解决!]
源码如下:
java
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// dependsOn表示当前beanName所依赖的,当前Bean创建之前dependsOn所依赖的Bean必须已经创建好了
for (String dep : dependsOn) {
// beanName是不是被dep依赖了,如果是则出现了循环依赖
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// dep被beanName依赖了,存入dependentBeanMap中,dep为key,beanName为value
registerDependentBean(dep, beanName);
// 创建所依赖的bean
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
8.判断bean是单例、原型、还是其他,然后进入不同if分支
创建单例Bean,执行Lambda表达式,创建Bean后需要放到单例池;之后还会创建factoryBean
创建原型Bean,不会将其放到单例池,仅仅是简单的创建;之后还会创建factoryBean
对于request、session、application,例如,在同一个request中,同一个BeanName拿到的是用一个Bean。主要通过这两个方法,request.getAttribute,获取bean;request.setAttribute,设置bean。SpringMVC在启动的时候,会将Scope注册到容器中,之后就可以直接拿到scope的值。
9.核心是创建单例Bean
sharedInstance = getSingleton(beanName, () -> {...})
从单例池找Bean,如果没有找到Bean,就使用Lambda表达式创建Bean。addSingleton(并添加到单例池)
核心方法:createBean
执行Lambda的核心代码:getSingleton
java
try {
singletonObject = singletonFactory.getObject(); // 执行Lambda表达式
newSingleton = true;
}
3.createBean
1.resolveBeanClass
马上就要实例化Bean了,确保beanClass被加载了
java
// 如果beanClass被加载了
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
// 如果beanClass没有被加载
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
return doResolveBeanClass(mbd, typesToMatch);// 加载类
}
2.resolveBeforeInstantiation
实例化前,执行实例化前的PostProcessor。
如果bean实现了InstantiationAwareBeanPostProcessor接口,并重写了invokeAwareMethods,可以在这里直接返回Bean,终止Spring创建该Bean(可以进行人工干预来创建bean)。如果在实例化前就返回了Bean,那么他需要做初始化后的操作。(和AOP有关)
3.doCreateBean
实例化,主要流程是下面的步骤
4.createBeanInstance
实例化Bean
5.applyMergedBeanDefinitionPostProcessors
该后置处理器的执行时机:实例化后,初始化前;作用:后置处理合并后的BeanDefinition
6.解决循环依赖
7.populateBean
作用:属性填充
在里面执行实例化后的方法(postProcessAfterInstantiation),
然后执行Spring自带的属性注入(ByType和ByName),
然后执行(InstantiationAwareBeanPostProcessor中的) AutowiredAnnotationBeanPostProcessor.postProcessProperties(),处理@Autowired注解。(处理属性注入的,@Autowired注解就是通过实现这个接口实现的依赖注入)
注意:在属性赋值之前,如果程序员已经为一些属性赋值了,那么就不会再重复赋值
byName 还是 byType导致注入太灵活,只要是个set方法就会被注入,容易出问题吧。
8.initializeBean
作用:初始化Bean
核心流程:
8.1invokeAwareMethods(包含设置beanName,bean类加载器、bean工厂:setBeanName、setBeanClassLoader、setBeanFactory)
8.2执行applyBeanPostProcessorsBeforeInitialization:初始化前的PostProcessor,包含使用@PostContruct注解和实现回调接口两种方法
初始化前有很多PostProcessor,比如下面这些
8.3invokeInitMethods:判断有无实现对应接口,执行初始化操作(是否实现InitializingBean)
8.4applyBeanPostProcessorsAfterInitialization:执行初始化后PostProcessor
9.判断初始化后的bean的依赖关系有没有改变,如果有改变,则可能会报错
和AOP有关,如果AOP之后产生新的bean,但是注入给其他bean的是原来的bean,并非最终生成的bean,那么在这里就会抛出异常
10.registerDisposableBeanIfNecessary
销毁Bean,判断bean是否有bean销毁的逻辑
4.bean销毁
销毁Bean的两个核心方法:
registerDisposableBeanIfNecessary:向Adapter中设置销毁逻辑。(适配器模式)
context.close():调用Adpter的销毁逻辑。
实现Bean销毁的方法:
1.实现DisposableBean接口,重写destroy方法;
2.使用PreDestroy注解
4.1.registerDisposableBeanIfNecessary
java
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {// 判断是否实现了销毁的接口
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
}
}
1.判断有没有指定销毁的方法
2.hasDestroyMethod
有无实现接口DisposableBean、AutoCloseable
3.hasDestructionAwareBeanPostProcessors
有没有实现DestructionAwareBeanPostProcessor,有没有重写requiresDestruction,重写了这个接口的方法,返回true,就需要销毁。
4.registerDisposableBean
把销毁逻辑存到disposableBeans,他是一个Map,Map<beanName,Adapter>。
这里用到适配器模式:new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc)
DisposableBeanAdapter中的核心方法:destroy
4.2.context.close()
java
/**
* Close this application context, destroying all beans in its bean factory.
* <p>Delegates to {@code doClose()} for the actual closing procedure.
* Also removes a JVM shutdown hook, if registered, as it's not needed anymore.
* @see #doClose()
* @see #registerShutdownHook()
*/
@Override
public void close() {
synchronized (this.startupShutdownMonitor) {
doClose();
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
// ignore - VM is already shutting down
}
}
}
}
核心方法是:doClose,调用Adpter的销毁逻辑
1.publishEvent
发布关闭事件
2.this.lifecycleProcessor.onClose();
关闭Spring容器的生命周期
3.destroyBeans
销毁Bean,以下步骤都是这个方法的操作。
4.destroySingletons-->destroySingleton
从单例池中移除掉Bean,如果存在依赖关系,则也要进行相应销毁
比如,A依赖B,那么B如果需要销毁,那么先销毁A,再销毁B
在这个方法中,会调用bean.destroy(),这里就进到了Adpter的销毁逻辑
5.遍历有销毁逻辑的Bean
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
执行clearSingletonCache,包含以下内容:
this.singletonObjects.clear(); 单例池
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
this.singletonsCurrentlyInDestruction = false;