源码分析spring容器启动销毁资源


       spring项目启动时,在bean的生命周期内,可以添加一些前置、后置处理,也可用于资源初始化、资源销毁。本文结合着源码对spring的一些扩展功能,执行顺序进行分析。先看bean初始化流程图,后面会对执行顺序进行详细介绍。
在这里插入图片描述

一、InitializingBean

       InitializingBean是一个接口,类实现了此接口,重写afterPropertiesSet方法,可以在bean实例化、属性赋值(populateBean方法)之后进行一些处理。

1.源码

public interface InitializingBean {
    
    
    void afterPropertiesSet() throws Exception;
}

       只包含一个afterPropertiesSet方法,子类实现了接口需要实现此方法。

2.spring boot源码调用

(1)位置

       处理此接口的源码调用位置如下:

run() -> 
this.refreshContext(context) -> 
this.refresh(context) -> 
applicationContext.refresh() -> 
this.finishBeanFactoryInitialization(beanFactory) -> 
beanFactory.preInstantiateSingletons() -> DefaultListableBeanFactory.preInstantiateSingletons() -> 
this.getBean(beanName) -> 
this.doGetBean() -> 
this.createBean(beanName, mbd, args) -> 
AbstractAutowireCapableBeanFactory.createBean() -> 
this.doCreateBean(beanName, mbdToUse, args) -> 
this.initializeBean(beanName, exposedObject, mbd) -> 
this.invokeInitMethods(beanName, wrappedBean, mbd) -> ((InitializingBean)bean).afterPropertiesSet()

(2)调用

       在bean进行初始化的时候,会执行invokeInitMethods初始化的方法,这个方法里面处理了对InitializingBean接口的afterPropertiesSet方法、用户自定义的初始化方法。用户自定义的方法指的是通过注解@Bean来申明一个bean时使用initMethod属性来指定的方法,申明bean除了@Bean还有@Component,@Component只能配置bean的名称,它可以直接在类上使用,spring容器会把它加载为一个bean;@Bean需要放在配置类(@Configuration修饰)中,放在基础类中spring是扫描不到的。

       @Component源码:

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
    
    
    String value() default "";
}

       使用@Bean配置自定义初始化方法:

@Configuration
public class BeanConfig {
    
    
    
    @Scope(value="singleton")
    @Bean(initMethod = "intMethod")
    public BeanDemo beanDemo(){
    
    
        return new BeanDemo("张三",18);
    }
}

       一个类既实现了InitializingBean接口,又配置了自定义initMethod方法,它的执行顺序是:先InitializingBean接口的方法-》initMethod方法,从invokeInitMethods方法源码可以看出:

  protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
    
    
        //bean对象实现了InitializingBean接口
        boolean isInitializingBean = bean instanceof InitializingBean;
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    
    
            if (this.logger.isTraceEnabled()) {
    
    
                this.logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }

            if (System.getSecurityManager() != null) {
    
    
                try {
    
    
                    AccessController.doPrivileged(() -> {
    
    
                        ((InitializingBean)bean).afterPropertiesSet();
                        return null;
                    }, this.getAccessControlContext());
                } catch (PrivilegedActionException var6) {
    
    
                    throw var6.getException();
                }
            } else {
    
    
                //先执行InitializingBean接口的afterPropertiesSet方法
                ((InitializingBean)bean).afterPropertiesSet();
            }
        }

        if (mbd != null && bean.getClass() != NullBean.class) {
    
    
            //获取bean自定义的初始化方法
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
    
    
                //使用反射执行自定义方法methodToInvoke.invoke(bean)
                this.invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

3.使用场景

       在xxl-job项目中有使用,通过afterPropertiesSet方法来初始化定时守护线程、创建线程池等。看下部分源码:

@Component
public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
    
    

    private static XxlJobAdminConfig adminConfig = null;
    public static XxlJobAdminConfig getAdminConfig() {
    
    
        return adminConfig;
    }

    // ---------------------- XxlJobScheduler ----------------------

    private XxlJobScheduler xxlJobScheduler;

    //实现了InitializingBean接口,在Bean初始化完并把参数注入成功后会调用afterPropertiesSet()
    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        adminConfig = this;

        xxlJobScheduler = new XxlJobScheduler();
        //初始化调度中心资源
        xxlJobScheduler.init();
    }

二、SmartInitializingSingleton

       SmartInitializingSingleton是一个接口,类实现了此接口,可以在bean实例化、初始化完成后进行后置处理,要求bean为单例且非懒加载的方式才会触发方法的执行,通过注解@Scope来指定bean为单例还是多实例,值为singleton:单例(全局有且只有一个实例),值为prototype:多实例(每次获取bean都是一个新实例),使用@Bean或者@Component声明的bean默认是单例的。

1.源码

public interface SmartInitializingSingleton {
    
    
    void afterSingletonsInstantiated();
}

       只有一个afterSingletonsInstantiated方法,子类可以实现此方法,进行资源的初始化。

2.spring boot源码调用

(1)位置

       处理此接口的源码调用位置如下:

run() -> 
this.refreshContext(context) -> 
this.refresh(context) -> 
applicationContext.refresh() -> 
this.finishBeanFactoryInitialization(beanFactory) -> 
beanFactory.preInstantiateSingletons() -> DefaultListableBeanFactory.preInstantiateSingletons() -> 
smartSingleton.afterSingletonsInstantiated()

(2)调用

       当bean已经完成实例化、初始化并执行完初始方法后才会处理SmartInitializingSingleton,使用while(true)来处理bean,先通过getBean实例化、初始化bean,并保存到缓存中,最后从缓存中取出bean,处理类型为SmartInitializingSingleton的bean,调用它的afterSingletonsInstantiated方法,所以此方法是bean初始化最后执行的方法。看下源码处理:

  do {
    
    
                while(true) {
    
    
                    RootBeanDefinition bd;
                    do {
    
    
                        do {
    
    
                            do {
    
    
                                if (!var2.hasNext()) {
    
    
                                    var2 = beanNames.iterator();

                                    while(var2.hasNext()) {
    
    
                                        beanName = (String)var2.next();
                                        //从缓存中获取bean
                                        Object singletonInstance = this.getSingleton(beanName);
                                        if (singletonInstance instanceof SmartInitializingSingleton) {
    
    
                                            StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);
                                            SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                            if (System.getSecurityManager() != null) {
    
    
                                                AccessController.doPrivileged(() -> {
    
    
                                                    smartSingleton.afterSingletonsInstantiated();
                                                    return null;
                                                }, this.getAccessControlContext());
                                            } else {
    
    
                                                                            smartSingleton.afterSingletonsInstantiated();//执行afterSingletonsInstantiated方法
                                            }

                                            smartInitialize.end();
                                        }
                                    }

                                    return;
                                }

                                beanName = (String)var2.next();
                                bd = this.getMergedLocalBeanDefinition(beanName);
                            } while(bd.isAbstract());
                        } while(!bd.isSingleton());
                    } while(bd.isLazyInit());

                    if (this.isFactoryBean(beanName)) {
    
    
                        bean = this.getBean("&" + beanName);
                        break;
                    }
                    //获取bean,会创建bean对象,并保存到缓存中
                    this.getBean(beanName);
                }
            } while(!(bean instanceof FactoryBean));

3.使用场景

       在xxl-job项目中有使用,当bean已经初始化完成,把bean中被@XxlJob修饰的方法添加到map集合中,初始化了netty服务器和线程池等。看下部分源码:

public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, SmartInitializingSingleton, DisposableBean {
    
    

    // 实现了SmartInitializingSingleton接口(只适用于单列bean),在bean实例初始化完成后,会调用afterSingletonsInstantiated方法
    @Override
    public void afterSingletonsInstantiated() {
    
    

        //初始化任务方法,处理所有Bean中使用@XxlJob注解标识的方法
        initJobHandlerMethodRepository(applicationContext);

        // refresh GlueFactory
        //重新设置GlueFactory的类型为SpringGlueFactory
        GlueFactory.refreshInstance(1);

        // super start
        try {
    
    
            //调用到XxlJobExecutor类的start方法,对一些资源进行初始化
            super.start();
        } catch (Exception e) {
    
    
            throw new RuntimeException(e);
        }
    }
}

三、@PostConstruct

       @PostConstruct是jdk的注解,也是用于初始化资源使用,spring使用InitDestroyAnnotationBeanPostProcessor对@PostConstruct、@PreDestroy注解进行包装,这样就可以使用BeanPostProcessor对使用了@PostConstruct、@PreDestroy修饰的方法进行调用。

1.源码

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
    
    
}

2.spring boot源码调用

(1)位置

       先看InitDestroyAnnotationBeanPostProcessor类的源码:

public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
    
    
    @Nullable
    private Class<? extends Annotation> initAnnotationType;
    @Nullable
    private Class<? extends Annotation> destroyAnnotationType;

    public InitDestroyAnnotationBeanPostProcessor() {
    
    
    }

    public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
    
    
        this.initAnnotationType = initAnnotationType;
    }

    public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
    
    
        this.destroyAnnotationType = destroyAnnotationType;
    }
}

       InitDestroyAnnotationBeanPostProcessor类实现了MergedBeanDefinitionPostProcessor接口,里面有两个类型为Annotation的属性,Annotation是所有注解的父类即@PostConstruct的父类,initAnnotationType用于标识接收初始化注解的类型,destroyAnnotationType用于标识接收销毁注解的类型,具体接收哪个注解由InitDestroyAnnotationBeanPostProcessor的子类CommonAnnotationBeanPostProcessor来实现。

       看下CommonAnnotationBeanPostProcessor部分源码:

public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
    
    

    public CommonAnnotationBeanPostProcessor() {
    
    
        this.setInitAnnotationType(PostConstruct.class);
        this.setDestroyAnnotationType(PreDestroy.class);
    }
}

        CommonAnnotationBeanPostProcessor类的默认构造函数设置了 initAnnotationType的类型为PostConstruct,destroyAnnotationType类型为PreDestroy。

       在注册BeanPostProcessor时,会向beanPostProcessors这个list集合添加一个CommonAnnotationBeanPostProcessor,这样在后面遍历beanPostProcessors集合执行postProcessBeforeInitialization方法时,会调用到InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization方法,此方法通过反射执行被@PostConstruct修饰的方法。

       注册BeanPostProcessor的源码位置:

run() -> 
this.refreshContext(context) -> 
this.refresh(context) -> 
applicationContext.refresh() -> 
this.registerBeanPostProcessors(beanFactory) -> 
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this) 

       处理BeanPostProcessor的源码位置:

run() -> 
this.refreshContext(context) -> 
this.refresh(context) -> 
applicationContext.refresh() -> 
this.finishBeanFactoryInitialization(beanFactory) -> 
beanFactory.preInstantiateSingletons() -> DefaultListableBeanFactory.preInstantiateSingletons() -> 
this.getBean(beanName) -> 
this.doGetBean() -> 
this.createBean(beanName, mbd, args) -> 
AbstractAutowireCapableBeanFactory.createBean() -> 
this.doCreateBean(beanName, mbdToUse, args) -> 
this.initializeBean(beanName, exposedObject, mbd) -> 
this.applyBeanPostProcessorsBeforeInitialization

(2)调用

       看下registerBeanPostProcessors注册的部分源码:

 public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    
    
        //从bean工厂获取到bean实现了BeanPostProcessor或者BeanPostProcessor子类的名称集合
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
        //注册BeanPostProcessor 
        registerBeanPostProcessors(beanFactory, (List)nonOrderedPostProcessors);
    }

    //注册BeanPostProcessor
    private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    
    
        Iterator var2 = postProcessors.iterator();
        while(var2.hasNext()) {
    
    
            BeanPostProcessor postProcessor = (BeanPostProcessor)var2.next();
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }
 
    //BeanPostProcessor添加到集合中
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    
    
        this.beanPostProcessors.remove(beanPostProcessor);
        this.beanPostProcessors.add(beanPostProcessor);
    }

       从bean工厂获取到bean实现了BeanPostProcessor或者BeanPostProcessor子类的集合,把他们添加到beanPostProcessors这个list集合中,bean中有方法被@PostConstruct或者@PreDestroy修饰,会匹配到CommonAnnotationBeanPostProcessor类。截图如下:
在这里插入图片描述

       在处理BeanPostProcessor集合时会调用到postProcessBeforeInitialization方法,看下它的入口initializeBean方法部分源码:

 protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    
    

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
    
    
            //遍历BeanPostProcessor集合,执行它的postProcessBeforeInitialization方法
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
    
    
            //执行初始化方法,包含InitializingBean和自定义InitMethod
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
    
    
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }

        return wrappedBean;
    }

       被@PostConstruct修饰的方法,遍历list到CommonAnnotationBeanPostProcessor类时会被调用,所以初始化执行顺序为:@PostConstruct-》InitializingBean接口的方法-》initMethod方法

注册进去的是CommonAnnotationBeanPostProcessor子类,postProcessBeforeInitialization方法定义在父类InitDestroyAnnotationBeanPostProcessor中,看下部分源码:

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        //获取被注解修饰的方法
        InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata metadata = this.findLifecycleMetadata(bean.getClass());
        metadata.invokeInitMethods(bean, beanName);
    }

   public void invokeDestroyMethods(Object target, String beanName) throws Throwable         {
    
    
       for(Iterator var5 = ((Collection)destroyMethodsToUse).iterator();
           var5.hasNext(); element.invoke(target)) {
    
    //使用反射执行方法

       }
    }

       通过bean获取到被@PostConstruct修饰的方法,使用反射执行对应的方法。

3.使用场景

       项目中可以用于初始化资源使用,例如从properties配置文件中获取到数据,但是数据格式需要再处理一下,可以使用@PostConstruct实现。

@Configuration
@ConfigurationProperties(prefix="inner.ignored")
@Data
public class ApiWhiteListConfig {
    
    

    //忽略的访问集合,key:ip,value:port
    private Map<String,String> ignoredMap = new HashMap<String,String>();
    private List<String> urlList;

    @PostConstruct
    public void init(){
    
    
        if(null != urlList && urlList.size() > 0){
    
    
            for(int i = 0;i < urlList.size();i++){
    
    
                String str = urlList.get(i);
                String[] arr = str.split(":");
                if(null != arr && arr.length == 2){
    
    
                    ignoredMap.put(arr[0],arr[1]);
                }
             }
        }
    }
}

四、DisposableBean

       DisposableBean是一个接口,用于bean销毁时做一些清理工作。

1.源码

public interface DisposableBean {
    
    
    void destroy() throws Exception;
}

       只有一个destroy方法,子类实现DisposableBean,重写它的方法。

2.spring boot源码调用

(1)位置

       处理此接口的源码调用位置如下:

run() -> 
this.refreshContext(context) -> 
this.refresh(context) -> 
applicationContext.refresh() -> 
this.finishBeanFactoryInitialization(beanFactory) -> 
beanFactory.preInstantiateSingletons() -> DefaultListableBeanFactory.preInstantiateSingletons() -> 
this.getBean(beanName) -> 
this.doGetBean() -> 
this.createBean(beanName, mbd, args) -> 
AbstractAutowireCapableBeanFactory.createBean() -> 
this.doCreateBean(beanName, mbdToUse, args) -> 
this.registerDisposableBeanIfNecessary(beanName, bean, mbd) ->
this.registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, this.getBeanPostProcessorCache().destructionAware, acc)) -> 
class DisposableBeanAdapter implements DisposableBean -> 
DisposableBeanAdapter.destroy() -> 
((DisposableBean)this.bean).destroy()

(2)调用

       在bean进行初始化完成后,方法registerDisposableBeanIfNecessary会注册DisposableBean,最终创建一个DisposableBeanAdapter对象,DisposableBeanAdapter类实现了DisposableBean接口。销毁资源的方式可以让类实现DisposableBean接口,重写destroy方法;也可以使用@Bean的方式声明bean对象,通过属性destroyMethod配置销毁方法,例如:

@Configuration
public class BeanConfig {
    
    

    @Scope(value="singleton")
    @Bean(destroyMethod = "destroyMethod")
    public BeanDemo beanDemo(){
    
    
        return new BeanDemo("张三",18);
    }

}

       也可以使用注解@PreDestroy在bean销毁之前执行方法,例如:

    @PreDestroy
    public void preDestroy(){
    
    
        System.out.println("=========【@PreDestroy】的preDestroy()方法===========");
    }

       这三种方法的执行顺序:@PreDestroy -》 DisposableBean-》destroyMethod。可以看下DisposableBeanAdapter的销毁源码:

    public void destroy() {
    
    
        if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
    
    
            Iterator var1 = this.beanPostProcessors.iterator();

            while(var1.hasNext()) {
    
    
                DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next();
                //调用被@PreDestroy注解修饰的方法执行
                processor.postProcessBeforeDestruction(this.bean, this.beanName);
            }
        }

        if (this.invokeDisposableBean) {
    
    
            if (logger.isTraceEnabled()) {
    
    
                logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
            }

            try {
    
    
                if (System.getSecurityManager() != null) {
    
    
                    AccessController.doPrivileged(() -> {
    
    
                        ((DisposableBean)this.bean).destroy();
                        return null;
                    }, this.acc);
                } else {
    
    
                    //执行实现了DisposableBean接口的destroy方法
                    ((DisposableBean)this.bean).destroy();
                }
            } catch (Throwable var3) {
    
    
                String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
                if (logger.isDebugEnabled()) {
    
    
                    logger.warn(msg, var3);
                } else {
    
    
                    logger.warn(msg + ": " + var3);
                }
            }
        }

        if (this.destroyMethod != null) {
    
    
            //执行自定义的destroyMethod方法
            this.invokeCustomDestroyMethod(this.destroyMethod);
        } else if (this.destroyMethodName != null) {
    
    
            Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
            if (methodToInvoke != null) {
    
    
                this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
            }
        }
    }

       前面分析了在注册beanPostProcessor时,会注册CommonAnnotationBeanPostProcessor类,当销毁时会调用到父类InitDestroyAnnotationBeanPostProcessor的postProcessBeforeDestruction,然后使用反射执行方法;再执行DisposableBean子类的destroy方法;最后使用反射执行自定义的destroyMethod方法。

3.使用场景

       在xxl-job项目中就有使用,用于清理资源,停止创建的守护线程,销毁线程池等后置工作。

@Component
public class XxlJobAdminConfig implements InitializingBean, DisposableBean {
    
    

    // 实现DisposableBean接口,重写它的bean销毁方法
    @Override
    public void destroy() throws Exception {
    
    
        xxlJobScheduler.destroy();
    }
}

五、@PreDestroy

       @PreDestroy是jdk的注解,用于销毁资源时的清理工作。

1.源码

@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
    
    
}

2.spring boot源码调用

(1)位置

       与@PostConstruct一致,详见@PostConstruct分析。

(2)调用

       在DisposableBean中已经分析,详见DisposableBean分析。

六、BeanPostProcessor

       BeanPostProcessor是一个接口,类实现了此接口,可以在bean实例化、属性赋值(populateBean方法)完成后,在开始进行初始化之前、初始化之后进行一些加强处理。某个类实现了BeanPostProcessor接口,则spring容器中所有bean进行实例化前后都会调用这个类重写的方法,可以用于所有bean的一些校验或者根据bean类型单独处理某些bean。

1.源码

public interface BeanPostProcessor {
    
    
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        return bean;
    }
}

       包含两个方法,postProcessBeforeInitialization初始化之前调用,postProcessAfterInitialization初始化之后调用。

2.spring boot源码调用

(1)位置

       处理此接口的源码调用位置如下:

run() -> 
this.refreshContext(context) -> 
this.refresh(context) -> 
applicationContext.refresh() -> 
this.finishBeanFactoryInitialization(beanFactory) -> 
beanFactory.preInstantiateSingletons() -> 
DefaultListableBeanFactory.preInstantiateSingletons() -> 
this.getBean(beanName) -> 
this.doGetBean() -> 
this.createBean(beanName, mbd, args) -> 
AbstractAutowireCapableBeanFactory.createBean() -> 
this.doCreateBean(beanName, mbdToUse, args) -> 
this.initializeBean(beanName, exposedObject, mbd) -> 
this.applyBeanPostProcessorsBeforeInitialization(bean, beanName) -> 
this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)

       在@PostConstruct介绍时已经给出注册BeanPostProcessor的源码位置:

run() -> 
this.refreshContext(context) -> 
this.refresh(context) -> 
applicationContext.refresh() -> 
this.registerBeanPostProcessors(beanFactory) -> 
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this) 

(2)调用

       我们先定义一个bean1,再定义一个实现了BeanPostProcessor的bean2,在bean2中可以对bean1初始化前后做一些处理。

       bean1的定义:

@Component
public class BeanDemo implements InitializingBean, DisposableBean{
    
    
    @Override
    public void destroy() throws Exception {
    
    
        System.out.println("=========【DisposableBean】的destroy()方法===========");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        System.out.println("=========【InitializingBean】的afterPropertiesSet()方法===========");
    }
}

       bean2的定义:

@Component
public class BeanDemo2 implements  BeanPostProcessor {
    
    
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        if(bean instanceof BeanDemo) {
    
    
            System.out.println("=========【BeanPostProcessor】的postProcessBeforeInitialization()方法===========");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        if(bean instanceof BeanDemo) {
    
    
            System.out.println("=========【BeanPostProcessor】的postProcessAfterInitialization()方法===========");
        }
        return bean;
    }
}

       在执行registerBeanPostProcessors方法注册BeanPostProcessor的时候,先注册的是实现了BeanPostProcessor接口的bean,再注册处理例如@PostConstruct注解的BeanPostProcessor,而注册到的是一个list集合中,这样在遍历list集合的时候,优先遍历实现了BeanPostProcessor接口的bean。看下注册的情况:
在这里插入图片描述
在这里插入图片描述

       看下初始化bean的initializeBean方法执行顺序部分源码:

   protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    
    

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
    
    
            //遍历BeanPostProcessor集合,执行postProcessAfterInitialization方法
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
    
    
            //执行初始化方法,包含InitializingBean和自定义InitMethod
            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;
    }

       从这可以看出初始化执行顺序:BeanPostProcessor实现类before-》@PostConstruct-》InitializingBean接口的方法-》initMethod方法-》BeanPostProcessor实现类after

       看下遍历BeanPostProcessor集合的方法源码:

    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    
    
        Object result = existingBean;

        Object current;
        //获取BeanPostProcessor集合
        for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
    
    
            BeanPostProcessor processor = (BeanPostProcessor)var4.next();
            //执行postProcessBeforeInitialization方法
            current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
    
    
                return result;
            }
        }

        return result;
    }

七、ApplicationContextAware

       ApplicationContextAware是一个接口类,类实现了此接口,重写它的方法即可获取ApplicationContext程序上下文,根据程序上下文可以获取到spring容器中的bean对象,然后根据业务需求对bean进行其他处理。

1.源码

public interface ApplicationContextAware extends Aware {
    
    
    void setApplicationContext(ApplicationContext var1) throws BeansException;
}

       只有一个setApplicationContext方法,子类重写此方法,在spring启动时即可接收ApplicationContext。

2.spring boot源码调用

(1)位置

       处理此接口的源码调用位置如下:

run() -> 
this.refreshContext(context) -> 
this.refresh(context) -> 
applicationContext.refresh() -> 
AbstractApplicationContext.refresh() -> 
this.prepareBeanFactory(beanFactory) -> 
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)) -> 
ApplicationContextAwareProcessor.postProcessBeforeInitialization() -> 
ApplicationContextAwareProcessor.invokeAwareInterfaces()

(2)调用

       关键的逻辑在这一行代码:

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))

       向存放BeanPostProcessor的list集合中加入ApplicationContextAwareProcessor,ApplicationContextAwareProcessor实现了BeanPostProcessor,后面spring处理每个bean时,会对这个集合进行遍历,调用每个对象的postProcessBeforeInitialization方法,并把当前处理的bean作为参数传递进去,在postProcessBeforeInitialization方法中判断当前bean是否实现了ApplicationContextAware接口,实现了则进行bean方法的调用。

       看下addBeanPostProcessor的方法:

   private final List<BeanPostProcessor> beanPostProcessors = new AbstractBeanFactory.BeanPostProcessorCacheAwareList();

   public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    
    
        Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
        this.beanPostProcessors.remove(beanPostProcessor);
        this.beanPostProcessors.add(beanPostProcessor);
    }

       之所以使用list形式存放BeanPostProcessor是因为list是有序的,先加入的对象先遍历到,这也是bean对象的setApplicationContext方法相比其他方法先执行的原因,添加这个BeanPostProcessor在prepareBeanFactory方法中,添加其他的BeanPostProcessor在registerBeanPostProcessors中,所以遍历BeanPostProcessor集合执行初始化方法的顺序:ApplicationContextAware-》BeanPostProcessor实现类before-》@PostConstruct-》InitializingBean接口的方法-》initMethod方法-》BeanPostProcessor实现类after。下面是refresh方法中注册BeanPostProcessor的两个入口截图:
在这里插入图片描述

       分析下ApplicationContextAwareProcessor#postProcessBeforeInitialization方法部分源码:

 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        //判断bean对象的类型是否属于这些aware,都不属于则直接返回bean
        if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware) && !(bean instanceof ApplicationStartupAware)) {
    
    
            return bean;
        } else {
    
    
            AccessControlContext acc = null;
            if (System.getSecurityManager() != null) {
    
    
                acc = this.applicationContext.getBeanFactory().getAccessControlContext();
            }

            if (acc != null) {
    
    
                AccessController.doPrivileged(() -> {
    
    
                    this.invokeAwareInterfaces(bean);
                    return null;
                }, acc);
            } else {
    
    
                //执行aware方法
                this.invokeAwareInterfaces(bean);
            }

            return bean;
        }
    }

    //根据bean对象是哪种类型,强制转成需要的类型,调用它定义的方法
    private void invokeAwareInterfaces(Object bean) {
    
    
        if (bean instanceof EnvironmentAware) {
    
    
            ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
        }

        if (bean instanceof ApplicationContextAware) {
    
    
            ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
        }

    }

       判断bean对象的类型是否属于这些aware,都不属于则直接返回bean,其中就有判断ApplicationContextAware类型的,包含需要处理的aware,则根据bean对象是哪种类型,强制转成需要的类型,调用它定义的方法,像setApplicationContext就是ApplicationContextAware接口的方法,类实现了ApplicationContextAware接口,重写setApplicationContext接收applicationContext,在这个阶段就会调用到实现类的setApplicationContext方法。

3.使用场景

       在xxl-job开源项目中就有使用,需要从spring容器中获取bean对象中使用了@XxlJob注解修饰的方法,把这些方法添加到map集合中,当定时器调用到具体的任务时,通过反射执行方法。需要获取bean对象就需要使用applicationContext上下文,所以实现ApplicationContextAware接口,重写setApplicationContext接收applicationContext。看下部分源码:

public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, SmartInitializingSingleton, DisposableBean {
    
    
   private static ApplicationContext applicationContext;

    //实现ApplicationContextAware接口,获取上下文,得到加载到spring容器中的所有bean对象
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    
    
        XxlJobSpringExecutor.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
    
    
        return applicationContext;
    }
}

八、Bean初始化销毁过程

     经过上面的分析,可以看出在spring启动时,初始化的流程为:添加ApplicationContextAwareProcessor到list集合中-》bean实现BeanPostProcessor则添加这个bean到list集合中-》添加CommonAnnotationBeanPostProcessor到list集合中-》初始化bean时遍历list,调用每个BeanPostProcessor的postProcessBeforeInitialization方法-》按list的加入顺序,执行ApplicationContextAware、BeanPostProcessor、CommonAnnotationBeanPostProcessor(@PostConstruct)-》执行InitializingBean接口方法-》执行自定义initMethod方法-》遍历list,调用每个BeanPostProcessor的postProcessAfterInitialization方法-》执行SmartInitializingSingleton接口方法

       bean初始化流程图:
在这里插入图片描述

       bean销毁流程图:
在这里插入图片描述

       来看一个demo,根据输出结果验证一下:

       bean1定义:

@Configuration
public class BeanConfig {
    
    

    @Scope(value="singleton")
    @Bean(initMethod = "intMethod",destroyMethod = "destroyMethod")
    public BeanDemo beanDemo(){
    
    
        return new BeanDemo("张三",18);
    }
}

public class BeanDemo implements ApplicationContextAware, SmartInitializingSingleton, InitializingBean, DisposableBean{
    
    

    private String name;
    private Integer age;

    public BeanDemo(String name, Integer age) {
    
    
        this.name = name;
        this.age = age;
        System.out.println("=========【BeanDemo】的有参构造方法===========");
    }

    @Override
    public void destroy() throws Exception {
    
    
        System.out.println("=========【DisposableBean】的destroy()方法===========");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    
    
        System.out.println("=========【InitializingBean】的afterPropertiesSet()方法===========");
    }

    @Override
    public void afterSingletonsInstantiated() {
    
    
        System.out.println("=========【SmartInitializingSingleton】的afterSingletonsInstantiated()方法===========");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    
    
        System.out.println("=========【ApplicationContextAware】的setApplicationContext()方法===========");
    }

    public void intMethod(){
    
    
        System.out.println("=========【intMethod】的intMethod()方法===========");
    }

    public void destroyMethod(){
    
    
        System.out.println("=========【destroyMethod】的destroyMethod()方法===========");
    }

    @PreDestroy
    public void preDestroy(){
    
    
        System.out.println("=========【@PreDestroy】的preDestroy()方法===========");
    }

    @PostConstruct
    public void postConstruct(){
    
    
        System.out.println("=========【@PostConstruct】的postConstruct()方法===========");
    }
}

       bean2定义:

@Component
public class BeanDemo2 implements  BeanPostProcessor {
    
    

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        if(bean instanceof BeanDemo) {
    
    
            System.out.println("=========【BeanPostProcessor】的postProcessBeforeInitialization()方法===========");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        if(bean instanceof BeanDemo) {
    
    
            System.out.println("=========【BeanPostProcessor】的postProcessAfterInitialization()方法===========");
        }
        return bean;
    }
}

       程序启动时输出结果:
在这里插入图片描述

       程序结果输出结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/ZHANGLIZENG/article/details/131131998