zoukankan      html  css  js  c++  java
  • Spring5源码分析之Bean生命周期

    Spring Bean生命周期的构成

    Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

    1. Bean自身的方法: 这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法
    2. Bean级生命周期接口方法: 这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
    3. 容器级生命周期接口方法:这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
    4. 工厂后处理器接口方法: 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

    生命周期

      创建  ----> 初始化 ---> 销毁

    1. 实例化对象

    2. setter注入,执行Bean的属性依赖注入

    3. BeanNameAware的setBeanName(), 如果实现该接口,则执行其setBeanName 方法

    4.BeanFactoryAware的setBeanFactory(), 如果实现该接口,则执行其setBeanFactory方法

    5. BeanPostProcessor的processBeforeInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processBeforeInitialization() 方法

    综上:

    // 后置处理器
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
        /**
         * 执行自定义init方法之前处理
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println( "3.[BeanPostProcessor] ---> postProcessBeforeInitialization 执行init方法[之前]处理") ;
            return bean;
        }
    
        /**
         * 执行自定义init方法之后处理
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println( "5.[BeanPostProcessor] ---> postProcessAfterInitialization 执行init方法[之后]处理") ;
    
            return bean;
        }
    }

    6. InitializingBean的afterPropertiesSet(), 如果实现了该接口,则执行其afterPropertiesSet()方法。Bean定义文件中定义init-method

    7.BeanPostProcessors的processAfterInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processAfterInitialization()方法

    8.DisposeablebBean的 destory(),在容器关闭时,如果Bean实现了这个接口,则执行他的destory()方法

    9. Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用“destory-method”定义的方法

    注:

     1. 单例默认时在容器被加载时候会初始化

     2. 多例在每次获取Bean的对象时候才会去初始化


     bean 初始化 指的就是对象已经创建里面所有的set方法都已经执行完毕了。 指定方法执行

       @Bean(initMethod , destory)   指定初始化和销毁方法  同时在bean中创建这两个方法

       init是在构造方法之前还是之后执行? 无参构造!  对象先创建完成后才进行初始化!所以先执行无参构造函数!

    补充到上面的过程:

      Bean的创建(执行构造函数) --> 初始化(自定义init方法) --> 销毁

      调用close() 方法销毁单例对象  

       注意:IOC容器使用Map结合存储对象,clear() 清除对象

       看源码:

    进入查看:

    继续点击查看:

    看第一个:

    持续跟进后就是 集合的 clear 方法了

     我们可以通过实现某些类 去进行初始化的操作!

    开发使用的方式:


    方法一: 通过@Bean指定init-method 和 destory-method

    方法二: 通过让Bean实现InitializingBean(定义初始化逻辑), DisposableBean(定义销毁逻辑)

    方法三: 使用JSR250(Java规范,不是Spring的): @PostConstruct: 在Bean创建完成并且赋值完成,来执行初始化方法。 @PreDestory: 在容器销毁Bean之前通知我们进行清理工作


    方法二:

    Bean:

    @Component
    public class LifeBean implements InitializingBean, DisposableBean {
    
        //构造函数
        public LifeBean() {
            System.out.println("LifeBean Constructor");
        }
    
        /** 接口InitializingBean的方法
         *  //解释 对象有创建 肯定也有给属相赋值的过程!,对象赋值完毕以后才执行该方法  即: (afterPropertiesSet)中文:set方法都走完了时候执行该方法
         * @throws Exception
         */
        @Override
        public void afterPropertiesSet() throws Exception {
            //等同于 @Bean(init =" ")
            //解释 对象有创建 肯定也有给属相赋值的过程!,对象赋值完毕以后才执行该方法
            System.out.println("LifeBean ********> 【InitializingBean.afterPropertiesSet】 ");
        }
    
        /**
         * 接口DisposableBean 的方法
         * @throws Exception
         */
        @Override
        public void destroy() throws Exception {
            System.out.println("LifeBean ********>【DisposableBean.destroy】");
        }
    }

    配置和扫包

    @Configuration
    @ComponentScan("com.toov5.config.beanTest.entity")
    public class MyConfig {
    
    }

    启动测试:

    public class test {
        public test(){
    
        }
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext1 = new AnnotationConfigApplicationContext("com.toov5.config");
            applicationContext1.close();
    //        System.out.println(applicationContext1);
        }
    }

    方法三

      注解代替了接口:

    Bean:

    @Component
    public class LifeBean {
    
        //构造函数
        public LifeBean() {
            System.out.println("LifeBean Constructor");
        }
        @PostConstruct
        public void afterPropertiesSet() throws Exception {
            //等同于 @Bean(init =" ")
            //解释 对象有创建 肯定也有给属相赋值的过程!,对象赋值完毕以后才执行该方法
            System.out.println("LifeBean ********> 【InitializingBean.afterPropertiesSet】 ");
        }
    
       @PreDestroy
        public void destroy() throws Exception {
            System.out.println("LifeBean ********>【DisposableBean.destroy】");
        }
    }

    效果是一样的:

      

    几个重要的Aware接口:


    1. ApplicationContextAware

    过滤器中,不可以使用注解方式获取Bean对象。 做法: 单独获取上下文ApplicationContext

    后置处理器,实现对Bean初始化增强功能

    @Component
    public class MyApplicationContext implements ApplicationContextAware {
        //开发时候经常做成全局的 进行使用
        private ApplicationContext applicationContext;
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            LifeBean lifeBean = applicationContext.getBean("lifeBean", LifeBean.class);
            System.out.println("result————————————————————"+lifeBean.toString());
        }
    }

    运行后:结果是没问题的

    问题: Spring底层中为什么能够实现ApplicationContextAware接口,就能够拿到ApplicationContext。

    2. BeanNameAware 与 BeanFactoryAware

     Bean

    @Component
    public class LifeBean01 implements BeanNameAware, BeanFactoryAware {
    
        public LifeBean01() {
            System.out.println("LifeBean01 对象实例化完成");
        }
    
        @Override
        public void setBeanName(String s) {
            System.out.println("beanName:"+s);
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("beanFactory:"+ beanFactory);
        }
    }

    配置类:

    @Configuration
    @ComponentScan("com.toov5.config.beanTest.entity")
    public class MyConfig {
    
    }

    测试:

    public class test {
        public test(){
    
        }
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext1 = new AnnotationConfigApplicationContext("com.toov5.config");
            applicationContext1.close();
    //        System.out.println(applicationContext1);
        }
    }

    IOC容器初始化到哪里独享都是循环遍历getBean方法。

    getSingleton(beanName) 先查询缓存有没有,看下之前有没有创建过

      Spring Bean生命周期中的后置处理器:  BeanPostProcessor接口


     从源码可以看到是 可以在 init之前或者之后进行一系列的操作的

    加上上面的那几个接口一起展示下:

    后置处理器,单独处理到别的bean里面去, 其他的bean(Spring 自带的都会走这个方法了)。

    init 之前之后,通过后置处理器对bean的初始化进行增强。 可以做bean耗时统计,日志打印等等。

    Bean:

    @Component
    public class LifeBean01 implements BeanNameAware, BeanFactoryAware, InitializingBean {
    
        public LifeBean01() {
            System.out.println("1. -----------------》LifeBean01 对象实例化完成");
        }
    
        @Override
        public void setBeanName(String s) {
            System.out.println("2. -----------------》对象beanName:"+s);
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("3. -----------------》beanFactory:"+ beanFactory);
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("5. -----------------》 bean init 方法执行");
        }
    }

    后置处理器:

    // 后置处理器
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor{
        /**
         * 执行自定义init方法之前处理
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println( beanName + "==========> 执行init方法[之前]处理");
            return bean;
        }
    
        /**
         * 执行自定义init方法之后处理
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println(beanName +"==========>执行init方法[之后]处理");
            return bean;
        }
    }

    配置类:

    @Configuration
    @ComponentScan("com.toov5.config.beanTest.entity")
    public class MyConfig {
    
    }

    测试:

    public class test {
        public test(){
    
        }
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext1 = new AnnotationConfigApplicationContext("com.toov5.config");
    //        applicationContext1.close();
    //        System.out.println(applicationContext1);
        }
    }

    结果:

     生命周期流程图:

    描述:

      1.实例化对象 (可以反射, 可以new)

      2. 给对象属性赋值

      3. 检查是否有Aware依赖,如果有上述的哪些,就进行执行。

    总结: 重点无非就是 Aware  和  后置处理器

    从源码中看 setApplicationContext() 方法是在前置获取的。 通过postProcessBefore前置,里面的默认方法获取到上下文对象。

    总结:

    后置处理器:

    @Component
    public class LifeBean implements BeanNameAware, BeanFactoryAware ,
            InitializingBean, DisposableBean {
    
        @Override
        public void setBeanName(String s) {
            System.out.println("1.[BeanNameAware] ---> setBeanName");
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("2.[BeanFactoryAware] ---> setBeanFactory");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("4.[InitializingBean] ---> afterPropertiesSet");
        }
    
        @Override
        public void destroy() throws Exception {
            System.out.println("6.[DisposableBean] ---> distory"  );
        }
    }

    Bean:

    // 后置处理器
    @Component
    public class MyBeanPostProcessor implements BeanPostProcessor {
        /**
         * 执行自定义init方法之前处理
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println( "3.[BeanPostProcessor] ---> postProcessBeforeInitialization 执行init方法[之前]处理") ;
            return bean;
        }
    
        /**
         * 执行自定义init方法之后处理
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println( "5.[BeanPostProcessor] ---> postProcessAfterInitialization 执行init方法[之后]处理") ;
    
            return bean;
        }
    }

    配置:

    @Configuration
    @ComponentScan("com.spring.test")
    public class config {
    
    
    }

    测试

    public class test {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext1 = new AnnotationConfigApplicationContext(config.class);
            applicationContext1.close();
        }
    }

  • 相关阅读:
    mac-chrome下手动安装vue-devtools
    python生成随机数、随机字符串
    windows下基于sublime text3的nodejs环境搭建
    解决webstorm卡顿问题
    【更改表单元素默认样式】更改文件上传按钮样式
    JavaScript判断用户是通过电脑端还是移动端访问
    【转载自W3CPLUS】如何将页脚固定在页面底部
    【前端插件】图片上传插件收集
    AngularJS 表单提交后显示验证信息与失焦后显示验证信息
    【转】包管理器Bower详细讲解
  • 原文地址:https://www.cnblogs.com/toov5/p/11257106.html
Copyright © 2011-2022 走看看