剑指Spring源码(三)俯瞰Spring的Bean的生命周期(大众版)

距离上一次写Spring源码解析,已经过去了快要好几个月了,主要原因还是Spring的源码解析类文章太难写了,不像我先前写的什么CAS源码,AQS源码,LinkedBlockingQueue等等,这些无非就是分析几个核心方法,代码也不算太长,就像比较复杂的AQS源码也是两篇搞定的,虽然AQS源码也很多东西也不能算是百分百的理解,但是核心思想应该是还算理解的。解析完毕成就感也满满的,写完博客,看着大段大段的文字,心里也很开心:哈哈哈,原来JDK源码也是可以读懂的,而且还能写出来。但是Spring源码就不一样了,如果和先前的源码分析类文章一样逐行去解析的话,那么可能一篇博客写下来,一个小小小小小方法都没法分析完,就算分析完毕了,也突出不了重点啊,但是Spring源码解析还是要继续的,就当做是自己的学习笔记把。

今天我们要看的内容是Spring Bean的生命周期,当然本篇博客只是带着大家俯瞰下,不会进行过多的源码分析,甚至只是贴下代码,不做分析,只是找到Spring Bean生命周期的回调或者钩子,当然这可能只是我的个人理解,大家还是要以怀疑的目光看待,也许我分析的是有问题的。

不知道Spring官方对Bean的生命问题是否有明确的定义或者解析,但是Spring In Action以及市面上流传的大部分博客是这样的:

为了验证上面的逻辑,可以做个试验:

首先定义了一个Bean,里面有各种回调和钩子,其中需要注意下,我在SpringBean的构造方法中打印了studentService,看SpringBean被new的出来的时候,studentService是否被注入了;又在setBeanName中打印了studentService,看此时studentService是否被注入了,以此来验证,Bean是何时完成的自动注入的(这个StudentServiceImpl 类的代码就不贴出来了,无非就是一个最普通的Bean):

public class SpringBean implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, BeanClassLoaderAware {

    public SpringBean() {
        System.out.println("SpringBean构造方法:" + studentService);
        System.out.println("SpringBean构造方法");
    }

    @Autowired
    StudentServiceImpl studentService;

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("destroy");
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("setBeanClassLoader");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("setBeanName:" + studentService);
        System.out.println("setBeanName");
    }

    public void initMethod() {
        System.out.println("initMethod");
    }

    public void destroyMethod() {
        System.out.println("destroyMethod");
    }
}

再定义一个BeanPostProcessor,在重写的两个方法中进行了判断,如果传进来的beanName是springBean才进行打印:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("springBean")) {
            System.out.println("postProcessBeforeInitialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(beanName.equals("springBean")) {
            System.out.println("postProcessAfterInitialization");
        }
        return bean;
    }
}

定义一个配置类,完成自动扫描,但是SpringBean是手动注册的,并且声明了initMethod和destroyMethod:

@Configuration
@ComponentScan
public class AppConfig {
    @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
    public SpringBean springBean() {
        return new SpringBean();
    }
}

最后就是启动类了:

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(AppConfig.class);
        annotationConfigApplicationContext.destroy();
    }

运行结果:

SpringBean构造方法:null
SpringBean构造方法
setBeanName:com.codebear.StudentServiceImpl@31190526
setBeanName
setBeanClassLoader
setBeanFactory
postProcessBeforeInitialization
afterPropertiesSet
initMethod
postProcessAfterInitialization
destroy
destroyMethod

可以看到,试验结果和上面分析的完全一致。

这就是广为流传的Spring生命周期。

也许你在应付面试的时候,是死记硬背这些结论的,现在我带着你找到这些方法,跟我来。

首先我们来到AnnotationConfigApplicationContext的构造方法:

    //根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        //&#x8C03;&#x7528;&#x65E0;&#x53C2;&#x6784;&#x9020;&#x51FD;&#x6570;&#xFF0C;&#x4F1A;&#x5148;&#x8C03;&#x7528;&#x7236;&#x7C7B;GenericApplicationContext&#x7684;&#x6784;&#x9020;&#x51FD;&#x6570;
        //&#x7236;&#x7C7B;&#x7684;&#x6784;&#x9020;&#x51FD;&#x6570;&#x91CC;&#x9762;&#x5C31;&#x662F;&#x521D;&#x59CB;&#x5316;DefaultListableBeanFactory&#xFF0C;&#x5E76;&#x4E14;&#x8D4B;&#x503C;&#x7ED9;beanFactory
        //&#x672C;&#x7C7B;&#x7684;&#x6784;&#x9020;&#x51FD;&#x6570;&#x91CC;&#x9762;&#xFF0C;&#x521D;&#x59CB;&#x5316;&#x4E86;&#x4E00;&#x4E2A;&#x8BFB;&#x53D6;&#x5668;&#xFF1A;AnnotatedBeanDefinitionReader read&#xFF0C;&#x4E00;&#x4E2A;&#x626B;&#x63CF;&#x5668;ClassPathBeanDefinitionScanner scanner
        //scanner&#x7684;&#x7528;&#x5904;&#x4E0D;&#x662F;&#x5F88;&#x5927;&#xFF0C;&#x5B83;&#x4EC5;&#x4EC5;&#x662F;&#x5728;&#x6211;&#x4EEC;&#x5916;&#x90E8;&#x624B;&#x52A8;&#x8C03;&#x7528; .scan &#x7B49;&#x65B9;&#x6CD5;&#x624D;&#x6709;&#x7528;&#xFF0C;&#x5E38;&#x89C4;&#x65B9;&#x5F0F;&#x662F;&#x4E0D;&#x4F1A;&#x7528;&#x5230;scanner&#x5BF9;&#x8C61;&#x7684;
        this();
        //&#x628A;&#x4F20;&#x5165;&#x7684;&#x7C7B;&#x8FDB;&#x884C;&#x6CE8;&#x518C;&#xFF0C;&#x8FD9;&#x91CC;&#x6709;&#x4E24;&#x4E2A;&#x60C5;&#x51B5;&#xFF0C;
        //&#x4F20;&#x5165;&#x4F20;&#x7EDF;&#x7684;&#x914D;&#x7F6E;&#x7C7B;
        //&#x4F20;&#x5165;bean&#xFF08;&#x867D;&#x7136;&#x4E00;&#x822C;&#x6CA1;&#x6709;&#x4EBA;&#x4F1A;&#x8FD9;&#x4E48;&#x505A;
        //&#x770B;&#x5230;&#x540E;&#x9762;&#x4F1A;&#x77E5;&#x9053;spring&#x628A;&#x4F20;&#x7EDF;&#x7684;&#x5E26;&#x4E0A;@Configuration&#x7684;&#x914D;&#x7F6E;&#x7C7B;&#x79F0;&#x4E4B;&#x4E3A;FULL&#x914D;&#x7F6E;&#x7C7B;&#xFF0C;&#x4E0D;&#x5E26;@Configuration&#x7684;&#x79F0;&#x4E4B;&#x4E3A;Lite&#x914D;&#x7F6E;&#x7C7B;
        //&#x4F46;&#x662F;&#x6211;&#x4EEC;&#x8FD9;&#x91CC;&#x5148;&#x628A;&#x5E26;&#x4E0A;@Configuration&#x7684;&#x914D;&#x7F6E;&#x7C7B;&#x79F0;&#x4E4B;&#x4E3A;&#x4F20;&#x7EDF;&#x914D;&#x7F6E;&#x7C7B;&#xFF0C;&#x4E0D;&#x5E26;&#x7684;&#x79F0;&#x4E4B;&#x4E3A;&#x666E;&#x901A;bean
        register(annotatedClasses);
        //&#x5237;&#x65B0;
        refresh();
    }

进入refresh方法,refresh方法中有一个finishBeanFactoryInitialization小方法,这个方法是用来实例化懒加载单例Bean的,也就是我们的Bean都是在这里被创建出来的(当然我这里说的的是绝大部分情况是这样的):

finishBeanFactoryInitialization(beanFactory);

我们再进入finishBeanFactoryInitialization这方法,里面有一个beanFactory.preInstantiateSingletons()方法:

        //&#x521D;&#x59CB;&#x5316;&#x6240;&#x6709;&#x7684;&#x975E;&#x61D2;&#x52A0;&#x8F7D;&#x5355;&#x4F8B;
        beanFactory.preInstantiateSingletons();

我们尝试再点进去,这个时候你会发现这是一个接口,好在它只有一个实现类,所以可以我们来到了他的唯一实现,实现类就是org.springframework.beans.factory.support.DefaultListableBeanFactory,这里面是一个循环,我们的Bean就是循环被创建出来的,我们找到其中的getBean方法:

getBean(beanName);

这里有一个分支,如果Bean是FactoryBean,如何如何,如果Bean不是FactoryBean如何如何,好在不管是不是FactoryBean,最终还是会调用getBean方法,所以我们可以毫不犹豫的点进去,点进去之后,你会发现,这是一个门面方法,直接调用了doGetBean方法:

    return doGetBean(name, null, null, false);

再进去,不断的深入,接近我们要寻找的东西。
这里面的比较复杂,但是有我在,我可以直接告诉你,下一步我们要进入哪里,我们要进入

if (mbd.isSingleton()) {

                    //getSingleton&#x4E2D;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A;&#x53C2;&#x6570;&#x7C7B;&#x578B;&#x662F;ObjectFactory<?>&#xFF0C;&#x662F;&#x4E00;&#x4E2A;&#x51FD;&#x6570;&#x5F0F;&#x63A5;&#x53E3;&#xFF0C;&#x4E0D;&#x4F1A;&#x7ACB;&#x523B;&#x6267;&#x884C;&#xFF0C;&#x800C;&#x662F;&#x5728;
                    //getSingleton&#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x8C03;&#x7528;ObjectFactory&#x7684;getObject&#xFF0C;&#x624D;&#x4F1A;&#x6267;&#x884C;createBean
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

这里面的createBean方法,再点进去啊,但是又点不进去了,这是接口啊,但是别慌,这个接口又只有一个实现类,所以说 没事,就是干,这个实现类为org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory。

这个实现的方法里面又做了很多事情,我们就不去看了,我就是带着大家找到那几个生命周期的回调到底定义在哪里就OK了。

    Object beanInstance = doCreateBean(beanName, mbdToUse, args);//&#x521B;&#x5EFA;bean&#xFF0C;&#x6838;&#x5FC3;
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;

再继续深入doCreateBean方法,这个方法又做了一堆一堆的事情,但是值得开心的事情就是 我们已经找到了我们要寻找的东西了。

首先是创建实例,位于:

instanceWrapper = createBeanInstance(beanName, mbd, args);//&#x521B;&#x5EFA;bean&#x7684;&#x5B9E;&#x4F8B;&#x3002;&#x6838;&#x5FC3;

其次是填充属性,位于:

populateBean(beanName, mbd, instanceWrapper);//&#x586B;&#x5145;&#x5C5E;&#x6027;&#xFF0C;&#x7092;&#x9E21;&#x91CD;&#x8981;

在填充属性下面有一行代码:

    exposedObject = initializeBean(beanName, exposedObject, mbd);

继续深入进去。

aware系列接口的回调位于initializeBean中的invokeAwareMethods方法:

invokeAwareMethods(beanName, bean);
private void invokeAwareMethods(final String beanName, final Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }

BeanPostProcessor的postProcessBeforeInitialization方法位于initializeBean的

if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

afterPropertiesSet init-method位于initializeBean中的

    invokeInitMethods(beanName, wrappedBean, mbd);

这里面调用了两个方法,一个是afterPropertiesSet方法,一个是init-method方法:

    ((InitializingBean) bean).afterPropertiesSet();
invokeCustomInitMethod(beanName, bean, mbd);

BeanPostProcessor的postProcessAfterInitialization方法位于initializeBean的

if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

当然在实际的开发中,应该没人会去销毁Spring的应用上下文把,所以剩余的两个销毁的回调就不去找了。

这就是广为流传的Spring Bean的生命周期,我也带着大家找到了各种回调和钩子,但是我认为这并非是Spring Bean完整的生命周期,只是经过简化的,那么我认为的完整的生命周期是如何的呢,请听下回分解。

Original: https://www.cnblogs.com/CodeBear/p/10867707.html
Author: CodeBear
Title: 剑指Spring源码(三)俯瞰Spring的Bean的生命周期(大众版)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/714718/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球