Spring Bean的生命同期Debug

摘要

Spring在启动的时候注册一个完整的Bean到容器的过程大致的分为注册、实例化、初始化、销毁!精妙的地方是在每个阶段Spring都对外提供了接口,用于扩展Bean在每个阶段的功能!

示例

@Component
public class BeanLifeCycle implements BeanNameAware,
        BeanFactoryAware, EnvironmentAware, ApplicationContextAware, ResourceLoaderAware, InitializingBean {

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
        System.out.println("Method:【setBeanFactory】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
    }

    @Override
    public void setBeanName(String s) {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
        System.out.println("Method:【setBeanName】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
        System.out.println("Method:【setApplicationContext】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
    }

    @Override
    public void setEnvironment(Environment environment) {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
        System.out.println("Method:【setEnvironment】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
        System.out.println("Method:【setResourceLoader】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
    }

    @PostConstruct
    public void PostConstruct() {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
        System.out.println("Method:【PostConstruct】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
    }

    @PreDestroy
    public void preDestroy() {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
        System.out.println("Method:【preDestroy】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
        System.out.println("Method:【afterPropertiesSet】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
    }
}
@Component
public class BeanInitial implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (BeanLifeCycle.class.getSimpleName().equalsIgnoreCase(beanName)) {
            final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
            System.out.println("Method:【postProcessBeforeInitialization】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (BeanLifeCycle.class.getSimpleName().equalsIgnoreCase(beanName)) {
            final StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
            System.out.println("Method:【postProcessAfterInitialization】" + "CallerClass:" + stackTraceElement.getClassName() + "#" + stackTraceElement.getMethodName());
        }
        return bean;
    }
}

输出分析

Method:【setBeanName】CallerClass:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
Method:【setBeanFactory】CallerClass:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
Method:【setEnvironment】CallerClass:org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces
Method:【setResourceLoader】CallerClass:org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces
Method:【setApplicationContext】CallerClass:org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces
Method:【postProcessBeforeInitialization】CallerClass:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
Method:【PostConstruct】CallerClass:sun.reflect.NativeMethodAccessorImpl#invoke0
Method:【afterPropertiesSet】CallerClass:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods
Method:【postProcessAfterInitialization】CallerClass:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
2021-09-03 16:22:06.551  INFO 81022 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2021-09-03 16:22:06.651  INFO 81022 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8082 (http) with context path ''
2021-09-03 16:22:06.665  INFO 81022 --- [  restartedMain] com.boot.boot.BootApplication            : Started BootApplication in 1.876 seconds (JVM running for 2.619)
Method:【preDestroy】CallerClass:sun.reflect.NativeMethodAccessorImpl#invoke0

打印出了函数调用Stack,通过打印出的日志,结合着源码看会更清楚一些!

posted @ 2021-09-03 16:34  乌托拉赛文  阅读(61)  评论(0编辑  收藏  举报