• @Bean 生命周期


    bean生命周期:

    实例bean

    1.当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法;

    2.根据配置情况调用Bean构造函数或工厂方法实例化Bean;

    3.如果容器注册了InstantiationAwareBeanPostProcessor接口,在实例化Bean之后,调用该接口的postProcessAfterInstantiation()方法,可在这里对已经实例化的对象进行一些"梳妆打扮";

    4.如果Bean配置了属性信息,容器在这一步着手将配置值设置到Bean对应的属性中,不过在设置每个属性之前将先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法;
    **
    **
    初始化和使用bean

    1:BeanNameAware的setBeanName():

    如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。

    2:BeanFactoryAware的setBeanFactory():

    如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。

    3:BeanPostProcessors的ProcessBeforeInitialization()

    如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调用。

    4:initializingBean的afterPropertiesSet():

    如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法

    5:Bean定义文件中定义init-method:

    可以在Bean定义文件中使用"init-method"属性设定方法名称例如:

    如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法

    6:BeanPostProcessors的ProcessaAfterInitialization()

    如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法

    BeanPostProcessor后处理器定义了两个方法:

    **       其一是postProcessBeforeInitialization()在第8步调用;其二是Object postProcessAfterInitialization(Object bean, String beanName)方法,这个方法在此时调用,容器再次获得对Bean进行加工处理的机会;**

    **       如果在中指定Bean的作用范围为scope="prototype",将Bean返回给调用者,调用者负责Bean后续生命的管理,Spring不再管理这个Bean的生命周期。如果作用范围设置为scope="singleton",则将Bean放入到Spring IoC容器的缓存池中,并将Bean引用返回给调用者,Spring继续对这些Bean进行后续的生命管理;**

     销毁bean

    此时,Bean已经可以被应用系统使用,并且将保留在BeanFactory中知道它不在被使用。有两种方法可以将其从BeanFactory中删除掉

    1:DisposableBean的destroy()

    在容器关闭时,如果Bean类有实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法

    2:Bean定义文件中定义destroy-method

    在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称,例如:

    如果有以上设定的话,则进行至这个阶段时,就会执行destroy()方法,如果是使用ApplicationContext来生成并管理Bean的话则稍有不同,使用ApplicationContext来生成及管理Bean实例的话,在执行BeanFactoryAware的setBeanFactory()阶段后,若Bean类上有实现org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,接着才执行BeanPostProcessors的ProcessBeforeInitialization()及之后的流程。

    代码:

    package com.company;
    
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.PropertyValues;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.beans.factory.DisposableBean;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
    import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    
    import java.beans.PropertyDescriptor;
    
    public class Main{
        public static void main(String[] args) {
            //①下面两句装载配置文件并启动容器
            Resource res = new ClassPathResource("beans.xml");
            BeanFactory bf = new XmlBeanFactory(res);
            
            //②向容器中注册MyBeanPostProcessor后处理器
            ((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor());
    
            //③向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
            ((ConfigurableBeanFactory)bf).addBeanPostProcessor(
                    new MyInstantiationAwareBeanPostProcessor());
            //④第一次从容器中获取worker,将触发容器实例化该Bean,这将引发Bean生命周期方法的调用。
            Worker worker1 = (Worker)bf.getBean("worker");
            System.out.println("第一次从容器中获取worker");
            worker1.printInfo();
            System.out.println("修改第一次从容器中获取worker的workType");
            worker1.setWorkType("正式工");
            System.out.println("第一次从容器中获取worker(修改过后的)");
            worker1.printInfo();
            //⑤第二次从容器中获取worker,直接从缓存池中获取
            System.out.println("第二次从容器中获取worker");
            Worker worker2= (Worker)bf.getBean("worker");
            worker2.printInfo();
            //⑥查看worker1和worker2是否指向同一引用
            System.out.println("查看worker1和worker2是否指向同一引用    ");
            System.out.println("worker1==worker2:"+(worker1==worker2));
            //⑦关闭容器
            ((XmlBeanFactory)bf).destroySingletons();
        }
    
    }
        //①管理Bean生命周期的接口
           class Worker implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean {
            private String name;
            private String workType;
            private int salary;
    
            public BeanFactory beanFactory;
            private String beanName;
    
            public void Worker(){
                System.out.println("调用worker()构造函数");
            }
    
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            public String getWorkType() {
                return workType;
            }
            public void setWorkType(String workType) {
                this.workType = workType;
            }
            public int getSalary() {
                return salary;
            }
            public void setSalary(int salary) {
                this.salary = salary;
            }
            public void printInfo() {
                System.out.println("name:" + name + ";workType:" + workType + ";salary:"
                        + salary);
            }
            //⑤DisposableBean接口方法
            @Override
            public void destroy() throws Exception {
                System.out.println("----------------销毁bean----------------------");
                System.out.println("调用DisposableBean.destroy()。");
    
            }
            //④InitializingBean接口方法
            @Override
            public void afterPropertiesSet() throws Exception {
                System.out.println("调用InitializingBean.afterPropertiesSet()。");
    
            }
            //③BeanNameAware接口方法
            @Override
            public void setBeanName(String arg0) {
                System.out.println("----------------初始化bean----------------------");
                System.out.println("调用BeanNameAware.setBeanName()。");
                this.beanName = arg0;
    
            }
            //②BeanFactoryAware接口方法
            @Override
            public void setBeanFactory(BeanFactory arg0) throws BeansException {
                System.out.println("调用BeanFactoryAware.setBeanFactory()。");
                this.beanFactory = arg0;
            }
    
            //⑥通过<bean>的init-method属性指定的初始化方法
            public void myInit() {
                System.out.println("调用init-method所指定的myInit(),将salary设置为600。");
                this.salary = 600;
            }
    
            //⑦通过<bean>的destroy-method属性指定的销毁方法
            public void myDestroy() {
                System.out.println("调用destroy-method所指定的myDestroy()。");
            }
    
        }
    
         class MyBeanPostProcessor implements BeanPostProcessor {
    
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName)
                    throws BeansException {
                if(beanName.equals("worker")){
                    Worker worker = (Worker)bean;
                    if(worker.getWorkType() == null){
                        System.out.println("调用BeanPostProcessor.postProcess AfterInitialization(),  getWorkType为空,设置为默认临时工");
                        worker.setWorkType("临时工");
                    }
                }
                return bean;
            }
    
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName)
                    throws BeansException {
                if(beanName.equals("worker")){
                    Worker worker = (Worker)bean;
                    if(worker.getSalary() >= 1000){
                        System.out.println("调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。");
                        worker.setSalary(800);
                    }
                }
                return bean;
            }
    
        }
    
          class MyInstantiationAwareBeanPostProcessor extends
                InstantiationAwareBeanPostProcessorAdapter {
            // ①接口方法:在实例化Bean前进行调用
            public Object postProcessBeforeInstantiation(Class beanClass,
                                                         String beanName) throws BeansException {
                System.out.println("----------------实例化bean----------------------");
                // ①-1仅对容器中worker Bean进行处理
                if ("worker".equals(beanName)) {
                    System.out
                            .println("InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation");
                }
                return null;
            }
    
            // ②接口方法:在实例化Bean后调用
            public boolean postProcessAfterInstantiation(Object bean, String beanName)
                    throws BeansException {
                // ②-1仅对容器中car Bean进行处理
                if ("worker".equals(beanName)) {
                    System.out
                            .println("InstantiationAware BeanPostProcessor.postProcess AfterInstantiation");
                }
                return true;
            }
    
            // ③接口方法:在设置某个属性时调用
            public PropertyValues postProcessPropertyValues(PropertyValues pvs,
                                                            PropertyDescriptor[] pds, Object bean, String beanName)
                    throws BeansException {
    
                // ③-1仅对容器中wroker Bean进行处理,还可以通过pdst入参进行过滤,
                // 仅对car的某个特定属性时进行处理。
                if ("worker".equals(beanName)) {
                    System.out
                            .println("Instantiation AwareBeanPostProcessor.postProcess PropertyValues");
                }
                return pvs;
            }
        }

    beans.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
        <bean id="worker" class="com.company.Worker"
              init-method="myInit"
              destroy-method="myDestroy"
              p:name="小强"
              p:salary="1000"
        />
    </beans>

    Result:

    ----------------实例化bean----------------------
    InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation
    InstantiationAware BeanPostProcessor.postProcess AfterInstantiation
    Instantiation AwareBeanPostProcessor.postProcess PropertyValues
    ----------------初始化bean----------------------
    调用BeanNameAware.setBeanName()。
    调用BeanFactoryAware.setBeanFactory()。
    调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。
    调用InitializingBean.afterPropertiesSet()。
    调用init-method所指定的myInit(),将salary设置为600。
    调用BeanPostProcessor.postProcess AfterInitialization(),  getWorkType为空,设置为默认临时工
    第一次从容器中获取worker
    name:小强;workType:临时工;salary:600
    修改第一次从容器中获取worker的workType
    第一次从容器中获取worker(修改过后的)
    name:小强;workType:正式工;salary:600
    第二次从容器中获取worker
    name:小强;workType:正式工;salary:600
    查看worker1和worker2是否指向同一引用    
    worker1==worker2:true
    ----------------销毁bean----------------------
    调用DisposableBean.destroy()。
    调用destroy-method所指定的myDestroy()。

    http://www.kancloud.cn/evankaka/springlearning/119661

    http://www.imooc.com/article/19449

    https://my.oschina.net/guanhe/blog/1408505

    http://blog.csdn.net/mack415858775/article/details/47721909

    https://zhuanlan.zhihu.com/p/25459839

    https://muyinchen.github.io/2017/08/23/Spring5%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90-@Autowired/

    http://www.shangyang.me/2017/04/05/spring-core-container-sourcecode-analysis-annotation-autowired/

  • 相关阅读:
    double保存小数点后两位
    二维数组做函数参数,及地址问题
    解决应用程序无法正常启动0xcxxxxxxxxxx问题
    docker+selenium grid解决node执行经常卡死
    docker+selenium Grid搭建自动化分布式测试环境
    Docker+Selenium Grid+Python搭建分布式测试环境
    xshell无法连接Ubuntu的解决办法
    docker获取镜像很慢解决办法
    django使用ajax传输数据
    $.ajax()所有参数详解
  • 原文地址:https://www.cnblogs.com/hongdada/p/6497246.html
Copyright © 2020-2023  润新知