Bean 的生命周期
一. 自定义 bean 的初始化与销毁逻辑
解释什么是 bean 的生命周期
bean 的生命周期,指 Spring 容器启动时, bean 的创建 — 初始化 — 销毁的过程,这个过程是由 Spring 容器来控制的, bean 的创建于销毁受到单例,多例,懒加载,非懒加载的影响, Spring 中默认是单例非懒加载
单例模式下, bean 的创建与销毁
在 Spring 启动创建容器完成时,会扫描需要注入到容器中的 bean, 如果不是懒加载,调用 bean 的构造器,创建 bean,并执行 bean 的初始化方法, 如果是懒加载,在获取这个 bean 时才会调用构造器,调用初始化方法进行初始化,单例模式下的销毁都是在关闭容器时执行的,调用销毁方法
多例模式下的 bean 的创建与销毁
多例模式下,在获取这个 bean 对象时容器只帮助创建初始化 bean,但是不会管理这个 bean, 关闭容器不会执行 bean 的销毁方法
- xml配置的传统方式,通过 init-method : 指定 bean 的初始化方法, destroy-method : 指定 bean 的销毁方法,在创建 bean 对象时会自动执行 init-method 指定的方法,对 bean 进行初始化操作,在close容器时,调用 destroy-method 指定的方法,来销毁对象(销毁此处只针对单例)
@Bean 设置 bean 的初始化与销毁时需要执行的方法
示例: 向容器中注入 Persion
- 创建 Persion 类,该类中提供创建于销毁的方法
public class Persion {
private String name="aaa";
public Persion(){
this.name = "aaa";
}
public Persion(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//初始化方法
public void init(){
System.out.println("初始化persion");
}
//销毁方法
public void detory(){
System.out.println("销毁persion");
}
}
- 使用 @Configuration 与 @Bean 创建配置类, 将 Persion 注入到容器中,@Bersion 注解设置 initMethod 与 destroyMethod 属性值,通过这两个值指定 Persion 初始化时与销毁时要执行的方法
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfiguration {
//注意如果设置为懒加载或多例时,是在获取 bean
//时才会执行创建,执行初始化,并且多例时,不会执行销毁方法
//@Scope("prototype")
@Bean(initMethod = "init", destroyMethod = "detory")
public Persion configMethod1(){
return new Persion();
}
}
- 调用测试
public static void main(String[] args) {
//1.获取ioc容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
//2.获取 bean,在单例非懒加载与多例时,获取bean才调用 Persion中的 init初始化方法
//Persion p = (Persion) context.getBean("configMethod1");
//3.关闭容器,多例时关闭容器并不会调用销毁方法
context.close();
}
InitializingBean 与 DisposableBean 接口方式指定执行与销毁时需要执行的方法
通过 InitializingBean 接口中的 afterPropertiesSet() 方法,执行初始化功能,通过 DisposableBean 接口中的 destroy() 方法执行销毁功能,需要向容器中注入的 bean 实现这两个接口并重写这两个方法
- 将 Persion 注入到容器中,并指定初始化方法,与销毁方法,Persion继承 InitializingBean, DisposableBean 这两个接口,并重写接口中的方法
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Persion implements InitializingBean, DisposableBean {
private String name="aaa";
public Persion(){
this.name = "aaa";
}
public Persion(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//InitializingBean 接口中的初始化方法,在初始化当前 bean时
//自动调用该方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化persion");
}
//DisposableBean 接口中的销毁方法,在销毁当前 bean 时自动调用该方法
@Override
public void destroy() throws Exception {
System.out.println("销毁persion");
}
}
- 注入配置类,此时如果容器操作 Persion 这个 bean ,就会执行 Persion 中自己定义的初始化,销毁方法
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfiguration {
//注意如果设置为懒加载或多例时,是在获取 bean
//时才会执行创建,执行初始化,并且多例时,不会执行销毁方法
//@Scope("prototype")
@Bean
public Persion configMethod1(){
return new Persion();
}
}
JSR250 注解指定初始化前与销毁前要执行的方法
将 Persion 注入到容器中,自定义初始化销毁方法,初始化方法使用 @PostConstruct修饰,销毁方法使用 @PreDestroy 修饰
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class Persion{
private String name="aaa";
public Persion(){
this.name = "aaa";
}
public Persion(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//在调用构造器完成后,通知调用该方法
@PostConstruct
public void afterPropertiesSet() throws Exception {
System.out.println("初始化persion");
}
//销毁 bean 之前通知调用该方法,有点像通知方法
@PreDestroy
public void destroy() throws Exception {
System.out.println("销毁persion");
}
}
BeanPostProcessor , bean 的后置处理器
- 什么是bean 的后置处理器: 在向 Spring 中注入bean时,会创建初始化这个 bean, 在初始化前后需要执行的逻辑代码,就可以看为后置处理器,需要用到BeanPostProcessor 接口,与接口中的两个方法,
- 自定义后置处理器
BeanPostProcessor ,接口中 postProcessBeforeInitialization(Object o, String s) 方法,初始化 bean 之前需要执行的方法, postProcessAfterInitialization(Object o, String s) 初始化之后需要执行的方法,创建一个类继承这个接口,并重写了里面的这两个方法后, 并将这个后置处理器注入到容器中, 后续在创建任何 bean 向容器中注入时(包括后置处理器本事,任何还是只有单例?),在初始化这个 bean 的前后,都会执行这两个方法
这两个方法中都有两个参数 Object o, String s, o代表执行初始化的bean, s 代表这个 bean 在容器中的 id
3.还有一个后置处理器接口 InstantiationAwareBeanPostProcessor 该接口继承 BeanPostProcessor 接口, 比 BeanPostProcessor 接口中多例一个 postProcessBeforeInstantiation() 方法, 该方法是在,创建 bean 前执行的
假设项目中需要向容器中注入bean 并且这些 bean在初始化前后需要执行某些操作, 创建后置处理器 MyBeanPostProcessor ,编写在初始化某些 bean 前后需要执行的代码 ,设置 MyBeanPostProcessor 继承 BeanPostProcessor 接口,重写接口中的这两个方法,在方法中编写初始化 bea 需要执行的逻辑代码
在初始化前后执行的方法中可以编写逻辑代码,例如判断当前初始化的bean是否是某个类型,如果做出某些操作等,可以参考Spring 提供的 ApplicationContextAwareProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
//不要忘记注入到容器中,此处使用的是单独配置的方式向容器中注入的
public class MyBeanPostProcessor implements BeanPostProcessor {
private String name="aaa";
public MyBeanPostProcessor (){
this.name = "aaa";
}
public Persion(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* @param o 当前需要初始化的 bean
* @param s 需要初始化的 bean,在容器中的 id
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println("初始化之前执行的逻辑工作");
return o;
}
/**
* @param o 当前初始化完成后的 bean
* @param s bean 在容器中的 id
* @return
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println("初始化之后执行的逻辑工作");
return o;
}
}
二. 通过 bean 的后置处理器,了解 bean 的生命周期
测试获取容器中的一个bean
public static void main(String[] args) {
//1.获取ioc容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
//2.获取 bean,在单例非懒加载与多例时,获取bean才调用 Persion中的 init初始化方法
//Persion p = (Persion) context.getBean("configMethod1");
//3.关闭容器,多例时关闭容器并不会调用销毁方法
context.close();
}
bean 的创建
- 在第一步时通过构造器创建 Spring 容器, 在创建容器时,会通过构造器调用抽象父类AbstractApplicationContext 中的 refresh() 方法刷新容器
- 查看 refresh() 刷新容器方法,重点关注
- registerBeanPostProcessors(); 该方法首先向容器中注册所有继承了 BeanPostProcessor 的 bean(包括间接继承与直接继承,Spring 自己提供的,与自定义创建的),方法中首先去容器中获取如果获取不到则创建,并存入容器中(创建的过程与下面finishBeanFactoryInitialization()相同都是调用 doGetBean() 方法,具体查看下面的finishBeanFactoryInitialization()) ,并且方法中会创建 Spring 自己提供的 BeanPostProcessor 到容器中,并且不同的 BeanPostProcessor 先后创建顺序不同
- finishBeanFactoryInitialization(); 创建所有单例对象(BeanPostProcessor 以外的单实例对象?)
- 查看 finishBeanFactoryInitialization() 方法,该方法需要一个 ConfigurableListableBeanFactory 类型对象,这是一个接口,在方法中,默认调用ConfigurableListableBeanFactory 的实现子类 DefaultListableBeanFactory 的 preInstantiateSingletons()方法,通过该方法创建所有单例对象
- 查看 preInstantiateSingletons() 方法, DefaultListableBeanFactory又继承了AbstractBeanFactory抽象父类, 在preInstantiateSingletons() 方法中会 while循环调用AbstractBeanFactory的 getBean(beanName)方法, beanName就是需要注入到容器中的 bean的名字,这个 beanName, 是通过一个ArrayList集合 beanDefinitionNames 获取的迭代器中取出的,这个集合中存放了所有要创建的单例 bean name,
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
//获取容器中的所有 beanName
List<String> beanNames = new ArrayList(this.beanDefinitionNames);
Iterator var2 = beanNames.iterator();
//遍历依次进行初始化和创建对象
while(true) {
while(true) {
String beanName;
RootBeanDefinition bd;
//do while循环,该循环的判断是,容器中的所bean 是否全部初始化完毕,
//在首次执行时,没有初始化完毕,会执行一次这个循环,获取一些定义信息
//如果走到条件判断中判断为未初始化完毕则执行下面,如果初始化完毕,则
//会执行所有bean初始化完毕要执行的方法,执行继承的SmartInitializingSingleton 中的
//afterSingletonsInstantiated()方法,具体参考"Spring 事件驱动模型开发"中的
//"了解 SmartInitializingSingleton"
do {
do {
do {
if (!var2.hasNext()) {
var2 = beanNames.iterator();
while(var2.hasNext()) {
beanName = (String)var2.next();
Object singletonInstance = this.getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
//执行所有bean初始化完成后的操作
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, this.getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
return;
}
beanName = (String)var2.next();
//获取bean的定义信息,例如获取这个bean是否是抽象的,是否是单实例的等待
bd = this.getMergedLocalBeanDefinition(beanName);
} while(bd.isAbstract());
} while(!bd.isSingleton());
//判断容器中的bean是否全部初始化完毕=========================
} while(bd.isLazyInit());
//===============下面才是真正的初始化bean=================
//判断是否是实现了"FactoryBean"接口的,如果是说明是一个工厂bean
if (this.isFactoryBean(beanName)) {
//工厂bean的创建方式
final FactoryBean<?> factory = (FactoryBean)this.getBean("&" + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = (Boolean)AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean)factory).isEagerInit();
}
}, this.getAccessControlContext());
} else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
}
if (isEagerInit) {
this.getBean(beanName);
}
} else {
//======我们要测试的单例bean执行此处的=======================
this.getBean(beanName);
}
}
}
}
- 查看AbstractBeanFactory 中的 getBean() 方法,方法中调用doGetBean()方法
- 在 doGetBean() 方法中会通过 getSingleton() 方法去获取 bean, 如果首次执行时,没有这个 bean, 则调用createBean() 创建这个 bean, 当这个bean创建初始化完成以后,会将这个bean放入 singletonObjects 集合中
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = this.transformedBeanName(name);
//========1.在缓存中获取 bean 是否已经被创建了(创建好的bean 都会被缓存起来,如果缓存中没有再出创建)====================
Object sharedInstance = this.getSingleton(beanName);
//==================================================================
Object bean;
if (sharedInstance != null && args == null) {
if (this.logger.isDebugEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//2.缓存中获取不到时,获取beanFactory
BeanFactory parentBeanFactory = this.getParentBeanFactory();
//获取父工厂(在正好了SpringMVC 后会出现父子容器)
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
}
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
//3.先来标记当前bean已经被创建了,防止多线程时两个线程同时创建同一个bean
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
try {
//4.拿到bean的定义信息
final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
//5.获取当前bean依赖的其它bean的信息
String[] dependsOn = mbd.getDependsOn();
String[] var11;
if (dependsOn != null) {
var11 = dependsOn;
int var12 = dependsOn.length;
for(int var13 = 0; var13 < var12; ++var13) {
String dep = var11[var13];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
this.registerDependentBean(dep, beanName);
//6.当前bean有依赖的bean,调用 getBean(dep) 方法先获取创建当前bean依赖的bean
this.getBean(dep);
}
}
//7.如果当前bean是单实例的
if (mbd.isSingleton()) {
//通过 getSingleTon() 创建这个单例对象
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
//createBean()方法创建对象
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
var11 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
Scope 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, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
AbstractBeanFactory.this.beforePrototypeCreation(beanName);
Object var1;
try {
var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
} finally {
AbstractBeanFactory.this.afterPrototypeCreation(beanName);
}
return var1;
}
});
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var21) {
throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var21);
}
}
} catch (BeansException var23) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var23;
}
}
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return this.getTypeConverter().convertIfNecessary(bean, requiredType);
} catch (TypeMismatchException var22) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var22);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
} else {
return bean;
}
}
- createBean() 方法是该抽象类中的抽象方法,在 AbstractAutowireCapableBeanFactory进行了实现 这个方法中重点的部分
- this.resolveBeforeInstantiation(beanName, mbdToUse); 通过后置处理器,创建当前 ben 的代理对象返回(Spring AOP 的搭建与源码分析)
- this.doCreateBean(beanName, mbdToUse, args); 如果后置处理器没有创建出代理对象,调用该方法进行实际创建
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating instance of bean '" + beanName + "'");
}
//bean的定义信息
RootBeanDefinition mbdToUse = mbd;
//要创建的bean的类型
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var7) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var7);
}
Object beanInstance;
try {
//======通过后置处理器,创建 当前需要创建的 bean 的代理对象并返回================
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
//==========================================================================
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
}
//=============创建 bean ===============
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
//======================================================
if (this.logger.isDebugEnabled()) {
this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
bean 的初始化
上面调用到 AbstractAutowireCapableBeanFactory 中的 doCreateBean() 方法创建 bean,继续跟踪 doCreateBean() 方法,查看在创建bean对象时做了哪些操作
- 查看 doCreateBean() 方法, 方法中首先调用会调用 populateBean() 方法, 对创建的 bean 的属性赋值 ,然后调用 initializeBean() 方法,执行创建这个 bean 的初始化方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//1.利用工厂方法,或者对象构造器等,创建 bean 的对象实例
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null;
Class<?> beanType = instanceWrapper != null ? instanceWrapper.getWrappedClass() : null;
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//2.遍历获取所有后置处理器,判断是否有MergedBeanDefinitionPostProcessor 这个类型的
//如果有,执行该后置处理器中的postProcessMergedBeanDefinition() 方法
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
//======3.调用 populateBean() 方法初始化bean实例,为创建的 bean 的属性赋值,
//该方法中还是会去获取所有的后置处理器,判断是否有 InstantiationAwareBeanPostProcessor类型的
//如果有执行该后置处理器中的postProcessAfterInstantiation()方法
//该方法中后续第二次获取InstantiationAwareBeanPostProcessor类型的后置处理器,
//执行这个处理器中的 postProcessPropertyValues()方法,两次获取后置处理器,是使用
//后置处理器获取属性要使用的值,只是获取,在方法的最后一步才会应用将获取的值设置到属性上
this.populateBean(beanName, mbd, instanceWrapper);
//====================================================================
if (exposedObject != null) {
//===============4.调用 initializeBean() 方法,执行创建当前bean所需要执行的初始化方法下面有对该方法的专门讲解(执行Aware中的方法,执行后置处理器中初始化之前的方法,执行初始化方法,执行后置处理器中初始化之后要执行的方法)===================
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
//==================================================================================================
}
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
//==================以上初始化bean 完成===============
if (earlySingletonExposure) {//第一次创建时不会执行该if内的方法?
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.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 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
//======注册 bean 的销毁方法(只是注册,销毁方法是在关闭容器时执行)=======
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
//最终返回创建的bean
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
- 查看 initializeBean() 方法,方法中调用了
- invokeAwareMethods() ,通过该方法,判读要初始化的bean 是否是实现了某个 Aware 接口的,如果是,调用执行实现接口,重写接口中的抽象方法(Aware,通常用来获取 Spring 提供的组件,通过重写的抽象方法赋值给当前初始化的 bean)
- applyBeanPostProcessorsBeforeInitialization() 方法,通过该方法执行所有初始化当前 bean 之前需要执行的方法
- invokeInitMethods() 方法,通过该方法执行初始化方法,例如我们自定义的一些初始化方法,框架中定义的一些初始化方法
- applyBeanPostProcessorsAfterInitialization() 方法,通过该方法执行所有初始化当前 bean 完成之后需要执行的方法
- 查看此处有点像前后通知的方法,方法内部会获取当前要初始化或初始化完成的这个 bean 是否是 BeanPostProcessor 的实现子类,如果是获取这个 bean 的所有 BeanPostProcessor ,然后循环调用初始化前后需要执行的方法,这样就是前面的BeanPostProcessor 后置处理器调用执行的原理
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
return null;
}
}, this.getAccessControlContext());
} else {
//=======判断当前要初始化的 bean 是实现了 Aware接口的,如果是,调用执行重写Aware 接口中的抽象方法====================
this.invokeAwareMethods(beanName, bean);
//=================================
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//=====执行初始化前的方法, 所有BeanPostProcessor 中的的 postProcessBeforeInitialization() 方法执行============
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//================初始化方法执行,例如通过@Bean指定的自定义初始化方法===============
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
//======执行初始化后的方法,所有BeanPostProcessor 中的postProcessAfterInitialization() 方法执行=============
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
- 查看执行初始化前需要执行的方法 applyBeanPostProcessorsBeforeInitialization(),初始化之后要执行的方跟该流程差不多,都是获取所有后置处理器调用后置处理器中的postProcessAfterInitialization()方法,此处就不截图了
- invokeAwareMethods(beanName, bean) 初始化方法
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = bean instanceof InitializingBean;
//1.判断当前bean是否是 InitializingBean 类型如果是,通过该接口中的方法进行初始化
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
((InitializingBean)bean).afterPropertiesSet();
return null;
}
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
((InitializingBean)bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
//2.判断是否自定义了初始化方法,如果自定义了
if (initMethodName != null && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { //执行自定义的初始化方法
this.invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
三. 根据初始化了解 Spring 底层BeanPostProcessor 的应用
查看 BeanPostProcessor 接口的实现类,会发现 Spring 对该接口提供了大量的实现类
1. 运行时获取 ioc 容器
例如 ApplicationContextAwareProcessor , 假设现在需要使用 Persion 拿到 ioc 容器
- 创建 Persion 类,该类实现ApplicationContextAware 接口,重写setApplicationContext() 方法
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class Persion implements ApplicationContextAware {
//运行时 Persion 对象需要拿到 Ioc容器
private ApplicationContext context;
public Persion(){
}
//通过重写 ApplicationContextAware 接口中的 setApplicationContext() 方法,对
//persion持有的容器赋值
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
}
- 此时 如果将 Persion 注入到容器中,通过容器获取到的 Persion 就会持有以赋值的ioc容器
- 是怎么做到的呢?: Spring 启动时默认提供一个后置处理器组件ApplicationContextAwareProcessor 注入到容器中,后续每个 bean 的创建都会被该组件监控到,执行 invokeAwareInterfaces() 方法,判断当前要创建的 bean 是否是 Aware 的直接子类或间接子类,如果是,调用这个 bean 重写的 Aware 中的抽象方法,获取 Spring 自己的组件赋值当前要创建的 bean 对象,给在向容器中注入Persion这个bean时,被 ApplicationContextAwareProcessor 监控到,调用 invokeAwareInterFaces() 方法,判断 Persion 是 ApplicationContextAware 的子类,调用当前bean重写 ApplicationContextAware 的 setApplicationContext() 方法,获取Spring容器,赋值给 Persion 中的context属性
2. 其它比较常用的
数据校验相关的
查看 BeanValidationProcessor 该类是 BeanPostProcessor 的实现子类,存放了数据校验相关的一些设置, 在 web 端数据校验时,将对象注入到容器中进行初始化,在初始化前对参数进行校验也是通过 BeanPostProcessor 来实现的
@Autowired 等相关的注入注解
在 Spring 中,向某个类注入一个属性 bean,使用@Autowired等一类的注解,底层也是通过BeanPostProcessor 实现子类 AutowiredAnnotationBeanPostProcessor 实现的
@Async
异步请求底层也是通过 BeanPostProcessor 实现的
四. 总结 Spring 中创建一个 bean 的执行流程
- Spring 创建 IOC 容器,在创建容器时调用 AbstractApplicationContext 中的 refresh() 方法刷新容器
- 在 refresh() 方法中首先调用 registerBeanPostProcessors(); 该方法首先向容器中注册所有继承了 BeanPostProcessor 的 bean(包括间接继承与直接继承,Spring 自己提供的,与自定义创建的,后续的创建bean对象的步骤与下面 finishBeanFactoryInitialization()方法中的相同) , finishBeanFactoryInitialization() 方法创建所有单例对象(BeanPostProcessor 以外的单实例对象?)
- 在finishBeanFactoryInitialization() 方法中会获取到一个ConfigurableListableBeanFactory 类型的对象beanFactory,通过这个对象默认调用它的实现子类 DefaultListableBeanFactory 中的 preInstantiateSingletons()方法
- 在DefaultListableBeanFactory 的 preInstantiateSingletons() 方法中会通过 while 循环调用AbstractBeanFactory的 getBean(beanName)方法, 在 getBean() 方法中调用 doGetBean() 方法中会通过 getSingleton() 方法去获取 bean, 如果首次执行时,没有这个 bean, 则调用AbstractAutowireCapableBeanFactory 子类实现的 createBean() 方法,在createBean()方法中通过调用 doCreateBean()
- .createBean()方法中在调用doCreateBean()方法以前首先会调用 resolveBeforeInstantiation(beanName, mbdToUse); 通过后置处理器,创建当前 ben 的代理对象返回(动态代理,在AOP中有详细讲解)
- doCreateBean() 方法中首先调用会调用 populateBean() 方法, 对创建的 bean 的属性赋值 ,然后调用 initializeBean() 方法,执行创建这个 bean 的初始化方法
- initializeBean() 方法中先后调用了三个主要的方法 :
- applyBeanPostProcessorsBeforeInitialization() 执行初始化前的方法,
- invokeInitMethods() 执行初始化方法,例如我们自定义的一些初始化方法,框架中定义的一些初始化方法
- applyBeanPostProcessorsAfterInitialization() 执行初始化后的方法
- 初始化前后的方法执行,主要是判断需要初始化的bean是否是 BeanPostProcessor 的实现子类,如果是,在初始化前,调用执行 postProcessBeforeInitialization() 方法, 在初始化后,调用执行 postProcessAfterInitialization() 方法