Spring Bean 初始化与销毁通

一. 自定义 bean 的初始化与销毁逻辑

解释什么是 bean 的生命周期
bean 的生命周期,指 Spring 容器启动时, bean 的创建 — 初始化 — 销毁的过程,这个过程是由 Spring 容器来控制的, bean 的创建于销毁受到单例,多例,懒加载,非懒加载的影响, Spring 中默认是单例非懒加载

单例模式下, bean 的创建与销毁
在 Spring 启动创建容器完成时,会扫描需要注入到容器中的 bean, 如果不是懒加载,调用 bean 的构造器,创建 bean,并执行 bean 的初始化方法, 如果是懒加载,在获取这个 bean 时才会调用构造器,调用初始化方法进行初始化,单例模式下的销毁都是在关闭容器时执行的,调用销毁方法

多例模式下的 bean 的创建与销毁
多例模式下,在获取这个 bean 对象时容器只帮助创建初始化 bean,但是不会管理这个 bean, 关闭容器不会执行 bean 的销毁方法

  1. xml配置的传统方式,通过 init-method : 指定 bean 的初始化方法, destroy-method : 指定 bean 的销毁方法,在创建 bean 对象时会自动执行 init-method 指定的方法,对 bean 进行初始化操作,在close容器时,调用 destroy-method 指定的方法,来销毁对象(销毁此处只针对单例)
    在这里插入图片描述

@Bean 设置 bean 的初始化与销毁时需要执行的方法

示例: 向容器中注入 Persion

  1. 创建 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");
    }
}

  1. 使用 @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();
    }

}
  1. 调用测试
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 实现这两个接口并重写这两个方法

  1. 将 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");
    }
}
  1. 注入配置类,此时如果容器操作 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 的后置处理器

  1. 什么是bean 的后置处理器: 在向 Spring 中注入bean时,会创建初始化这个 bean, 在初始化前后需要执行的逻辑代码,就可以看为后置处理器,需要用到BeanPostProcessor 接口,与接口中的两个方法,
  2. 自定义后置处理器
    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 的创建

  1. 在第一步时通过构造器创建 Spring 容器, 在创建容器时,会通过构造器调用抽象父类AbstractApplicationContext 中的 refresh() 方法刷新容器
    在这里插入图片描述
  2. 查看 refresh() 刷新容器方法,重点关注
  • registerBeanPostProcessors(); 该方法首先向容器中注册所有继承了 BeanPostProcessor 的 bean(包括间接继承与直接继承,Spring 自己提供的,与自定义创建的),方法中首先去容器中获取如果获取不到则创建,并存入容器中(创建的过程与下面finishBeanFactoryInitialization()相同都是调用 doGetBean() 方法,具体查看下面的finishBeanFactoryInitialization()) ,并且方法中会创建 Spring 自己提供的 BeanPostProcessor 到容器中,并且不同的 BeanPostProcessor 先后创建顺序不同
  • finishBeanFactoryInitialization(); 创建所有单例对象(BeanPostProcessor 以外的单实例对象?)
    在这里插入图片描述
  1. 查看 finishBeanFactoryInitialization() 方法,该方法需要一个 ConfigurableListableBeanFactory 类型对象,这是一个接口,在方法中,默认调用ConfigurableListableBeanFactory 的实现子类 DefaultListableBeanFactory 的 preInstantiateSingletons()方法,通过该方法创建所有单例对象
    在这里插入图片描述
  2. 查看 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);
                }
            }
        }
    }
  1. 查看AbstractBeanFactory 中的 getBean() 方法,方法中调用doGetBean()方法
    在这里插入图片描述
  2. 在 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;
        }
    }

  1. 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对象时做了哪些操作

  1. 查看 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);
        }
    }
  1. 查看 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;
    }

  1. 查看执行初始化前需要执行的方法 applyBeanPostProcessorsBeforeInitialization(),初始化之后要执行的方跟该流程差不多,都是获取所有后置处理器调用后置处理器中的postProcessAfterInitialization()方法,此处就不截图了
    在这里插入图片描述
  2. 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 容器

  1. 创建 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;
    }
}
  1. 此时 如果将 Persion 注入到容器中,通过容器获取到的 Persion 就会持有以赋值的ioc容器
  2. 是怎么做到的呢?: 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 的执行流程

  1. Spring 创建 IOC 容器,在创建容器时调用 AbstractApplicationContext 中的 refresh() 方法刷新容器
  2. 在 refresh() 方法中首先调用 registerBeanPostProcessors(); 该方法首先向容器中注册所有继承了 BeanPostProcessor 的 bean(包括间接继承与直接继承,Spring 自己提供的,与自定义创建的,后续的创建bean对象的步骤与下面 finishBeanFactoryInitialization()方法中的相同) , finishBeanFactoryInitialization() 方法创建所有单例对象(BeanPostProcessor 以外的单实例对象?)
  3. 在finishBeanFactoryInitialization() 方法中会获取到一个ConfigurableListableBeanFactory 类型的对象beanFactory,通过这个对象默认调用它的实现子类 DefaultListableBeanFactory 中的 preInstantiateSingletons()方法
  4. 在DefaultListableBeanFactory 的 preInstantiateSingletons() 方法中会通过 while 循环调用AbstractBeanFactory的 getBean(beanName)方法, 在 getBean() 方法中调用 doGetBean() 方法中会通过 getSingleton() 方法去获取 bean, 如果首次执行时,没有这个 bean, 则调用AbstractAutowireCapableBeanFactory 子类实现的 createBean() 方法,在createBean()方法中通过调用 doCreateBean()
  5. .createBean()方法中在调用doCreateBean()方法以前首先会调用 resolveBeforeInstantiation(beanName, mbdToUse); 通过后置处理器,创建当前 ben 的代理对象返回(动态代理,在AOP中有详细讲解)
  6. doCreateBean() 方法中首先调用会调用 populateBean() 方法, 对创建的 bean 的属性赋值 ,然后调用 initializeBean() 方法,执行创建这个 bean 的初始化方法
  7. initializeBean() 方法中先后调用了三个主要的方法 :
    • applyBeanPostProcessorsBeforeInitialization() 执行初始化前的方法,
    • invokeInitMethods() 执行初始化方法,例如我们自定义的一些初始化方法,框架中定义的一些初始化方法
    • applyBeanPostProcessorsAfterInitialization() 执行初始化后的方法
    • 初始化前后的方法执行,主要是判断需要初始化的bean是否是 BeanPostProcessor 的实现子类,如果是,在初始化前,调用执行 postProcessBeforeInitialization() 方法, 在初始化后,调用执行 postProcessAfterInitialization() 方法
发布了48 篇原创文章 · 获赞 0 · 访问量 583

猜你喜欢

转载自blog.csdn.net/qq_29799655/article/details/105309538