zoukankan      html  css  js  c++  java
  • Spring的Bean的生命周期(大众版)

     

     

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

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

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

    1. 实例化Bean对象,这个时候Bean的对象是非常低级的,基本不能够被我们使用,因为连最基本的属性都没有设置,可以理解为连Autowired注解都是没有解析的;
    2. 填充属性,当做完这一步,Bean对象基本是完整的了,可以理解为Autowired注解已经解析完毕,依赖注入完成了;
    3. 如果Bean实现了BeanNameAware接口,则调用setBeanName方法;
    4. 如果Bean实现了BeanClassLoaderAware接口,则调用setBeanClassLoader方法;
    5. 如果Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法;
    6. 调用BeanPostProcessor的postProcessBeforeInitialization方法;
    7. 如果Bean实现了InitializingBean接口,调用afterPropertiesSet方法;
    8. 如果Bean定义了init-method方法,则调用Bean的init-method方法;
    9. 调用BeanPostProcessor的postProcessAfterInitialization方法;当进行到这一步,Bean已经被准备就绪了,一直停留在应用的上下文中,直到被销毁;
    10. 如果应用的上下文被销毁了,如果Bean实现了DisposableBean接口,则调用destroy方法,如果Bean定义了destory-method声明了销毁方法也会被调用。

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

    首先定义了一个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) {
            //调用无参构造函数,会先调用父类GenericApplicationContext的构造函数
            //父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory
            //本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefinitionScanner scanner
            //scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的
            this();
            //把传入的类进行注册,这里有两个情况,
            //传入传统的配置类
            //传入bean(虽然一般没有人会这么做
            //看到后面会知道spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配置类
            //但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通bean
            register(annotatedClasses);
            //刷新
            refresh();
        }

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

    finishBeanFactoryInitialization(beanFactory);

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

            //初始化所有的非懒加载单例
            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中的第二个参数类型是ObjectFactory<?>,是一个函数式接口,不会立刻执行,而是在
                        //getSingleton方法中,调用ObjectFactory的getObject,才会执行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);//创建bean,核心
                if (logger.isDebugEnabled()) {
                    logger.debug("Finished creating instance of bean '" + beanName + "'");
                }
                return beanInstance;

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

    创建实例

    首先是创建实例,位于:

    instanceWrapper = createBeanInstance(beanName, mbd, args);//创建bean的实例。核心

    填充属性

    其次是填充属性,位于:

    populateBean(beanName, mbd, instanceWrapper);//填充属性,炒鸡重要

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

        exposedObject = initializeBean(beanName, exposedObject, mbd);

    继续深入进去。

    aware系列接口的回调

    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方法

    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

    afterPropertiesSet init-method位于initializeBean中的

        invokeInitMethods(beanName, wrappedBean, mbd);

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

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

    BeanPostProcessor的postProcessAfterInitialization方法

    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完整的生命周期,只是经过简化的,那么我认为的完整的生命周期是如何的呢,请听下回分解。

  • 相关阅读:
    【已解决】Android ADT中增大AVD内存后无法启动:emulator failed to allocate memory
    XE10 塔建 Android 开发环境 (已测试通过)
    Erstudio8.0怎么用?Erstudio8.0汉化版详细使用教程
    Excel 信息对比_数组版
    百万级数据查询优化(数据库)
    sql查询重复记录、删除重复记录方法大全
    JS和JSON的区别
    JS中字符串的true转化为boolean类型的true
    关于HTTP协议,一篇就够了
    关于JS的prototype
  • 原文地址:https://www.cnblogs.com/shoshana-kong/p/10877270.html
Copyright © 2011-2022 走看看