spring基本使用(5)-BeanFactory中bean的生命周期

1、借用一张BeanFactory中bean的生命周期流程图:

   
[BeanFactory生命周期流程图]


2、BeanFactory生命周期涉及组件说明:
    2.1、InstantiationAwareBeanPostProcessorbean:实例化后置处理器
            主要职责:
             1、postProcessBeforeInstantiation接口方法就是在bean实例化之前做相应的处理。
             2、postProcessAfterInstantiation接口方法就是在bean实例化之后做相应处理。
             3、postProcessPropertyValues接口方法就是在bean实例化之后设置bean属性之前做相应处理。
             用法:实现InstantiationAwareBeanPostProcessor接口,此处应该注意,InstantiationAwareBeanPostProcessor继承了后面的一个组件BeanPostProcessor接口,如果实现InstantiationAwareBeanPostProcessor此接口就一定也要实现BeanPostProcessor的函数,但是此时bean还没有到BeanPostProcessor函数的处理周期,因此会让人有混淆InstantiationAwareBeanPostProcessor的职责,因此,为了区分开来InstantiationAwareBeanPostProcessor与BeanPostProcessor的职责,spring提供了一个InstantiationAwareBeanPostProcessorAdapter抽象类适配器来区分,因此,我们只需要继承InstantiationAwareBeanPostProcessorAdapter抽象类,重写职责中的三个函数,并且通过工厂的addBeanPostProcessor将其添加到BeanFactory即可。

    2.2、BeanNameAware:bean名称设置感知器
          主要职责:在设置bean属性值之后提供设置bean name的操作。
          用法:需要有设置Bean name 的bean实现此接口重写setBeanName函数即可。

    2.3、BeanFactoryAware:bean 工厂实例感知器
          主要职责:在BeanNameAware之后让bean 知道自己所在的Bean工厂。
          用法:需要知道自己所在的bean 工厂的bean实现此接口重写setBeanFactory函数即可。


    2.4、BeanPostProcessor:bean 初始化后置处理器
          主要职责:
           1、postProcessBeforeInitialization接口方法就是在bean 初始化之前做相应处理。
           2、postProcessAfterInitialization接口方法就是在 初始化完成之后做相应处理。
          用法:自定义实现BeanPostProcessor接口,然后后通过factory的addBeanPostProcessor将其添加到BeanFactory即可。

    2.5、InitializingBean:bean初始化处理器
          主要职责:afterPropertiesSet()方法可提供bean初始化功能。
          用法:需要提供初始化的bean实现此接口重写afterPropertiesSet()完成自己的业务逻辑。

    2.6、<bean/>的init-method 属性
          <bean/> 标签定义的初始化函数属性 ,@PostConstruct只针对ApplicationContext加载的时候才能被处理。
          主要职责: 使用xml的方式配置bean的初始化函数,在InitializingBean.afterPropertiesSet()之后 BeanPostProcessor.postProcessAfterInitialization()之前做相应处理。
          用法:在需要初始化的bean中定义好初始化函数,然后在<bean/>中配置在此属性即可。

    2.7、DisposableBean:bean销毁处理器
          主要职责:在容器销毁bean之前做相应处理。
          用法:有需要做bean销毁前做业务处理的bean实现此接口重写destroy()函数可。

    2.8、<bean/>destroy-method属性
           <bean/>标签属性定义bean销毁前处理逻辑,@PreDestroy只针对ApplicationContext加载的时候才能被处理。。
          主要职责:在DisposableBean之后bean销毁i前做相应处理。
          用法:同init-method属性
                   
    2.9、BeanFactory.getBean()流程             
           Car car = factory.getBean(Car.class);                     
           beanFactory.getBean()触发如下:
             1、调用添加的所有InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()方法。
             2、实例化bean。
             3、调用添加的所有InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()方法。
             4、调用添加的所有InstantiationAwareBeanPostProcessor.postProcessPropertyValues()方法。
             5、如果bean实现了BeanNameAware接口,调用bean的setBeanName()函数。
             6、如果bean实现了BeanFactoryAware接口,调用bean的setBeanFactory()函数。
             7、调用添加的所有BeanPostProcessor.postProcessBeforeInitialization()方法。
             8、如果bean实现了InitializingBean接口,调用bean的afterPropertiesSet()方法。
             9、如果<bean/>上定义的init-method 属性,则调用bean中的init-method属性值的方法。
            10、调用添加的所有BeanPostProcessor.postProcessAfterInitialization()方法。

        销毁bean触发如下:
            11、如果bean实现了DisposableBean接口,则调用bean中的destroy()方法。
            12、如果<bean/>上定义的destroy-method 属性,则调用bean中的destroy-method属性值的方法。

    2.10、BeanFactory.getBean()方法测试结果
            getBean触发如下流程测试输出:
            1、InstantiationAwareBeanPostProcessor 的 before。。。  每个bean生命周期中都会触发一次       
            2、Construct...                                                                       每个bean生命周期中都会触发一次   
            3、InstantiationAwareBeanPostProcessor 的 after。。。     每个bean生命周期中都会触发一次  
            4、InstantiationAwareBeanPostProcessor 的 postProcessPropertyValues。。。 每个bean生命周期中都会触发一次   
            5、BeanPostProcessor 的 before。。。                                 每个bean生命周期中都会触发一次   
            6、InitializingBean 的afterPropertiesSet。。。                      bean如果配置了则生命周期中都会触发一次
            7、<bean/> init-method 属性。。。                                      bean如果配置了则生命周期中都会触发一次
            8、BeanPostProcessor 的 after。。。                                     每个bean生命周期中都会触发一次   
            9、DisposableBean 的 destroy。。。                                     bean如果配置了则生命周期中都会触发一次
           10、<bean/> destroy-method 属性。。。                              bean如果配置了则生命周期中都会触发一次

3、测试代码:

public class Bar implements InitializingBean,DisposableBean {

    private String price;

    public Bar() {
        System.out.println("Construct...");
    }

    public String getPrice() { return price;}

    public void setPrice(String price) {this.price = price;}

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

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

    public void myinit(){ System.out.println("<bean/> init-method 属性。。。");}
    public void mydestroy(){ System.out.println("<bean/> destroy-method 属性。。。");}

}


public class MyInstantiationAwareBeanPostProcessor extends
                                    InstantiationAwareBeanPostProcessorAdapter {

    @Override
    public Object postProcessBeforeInstantiation(Class <?> aClass, 
                                                 String s)throws BeansException {
        if (s.equals("bar")){
            System.out.println("InstantiationAwareBeanPostProcessor 的 before。。。");
        }
        return null;
    }


    @Override
    public boolean postProcessAfterInstantiation(Object o, String s)
                                                           throws BeansException {
        if (s.equals("bar")){
            System.out.println("InstantiationAwareBeanPostProcessor 的 after。。。");
        }
        return false;
    }



    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues propertyValues,
                                          PropertyDescriptor[] propertyDescriptors,
                                          Object o, String s)
                                                    throws BeansException {
        if (s.equals("bar")){
            System.out.println("InstantiationAwareBeanPostProcessor 的 
                                              postProcessPropertyValues。。。");
        }
        return propertyValues;
    }

}



public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object o, String s)
                                                            throws BeansException {
        if (s.equals("bar")){
            System.out.println("BeanPostProcessor 的 before。。。");
        }
        return o;
    }


    @Override
    public Object postProcessAfterInitialization(Object o, String s)
                                                           throws BeansException {
        if (s.equals("bar")){
            System.out.println("BeanPostProcessor 的 after。。。");
        }
        return o;
    }

}



<bean id="bar" class="com.wzy.springstudy.beanfactoryprocess.Bar" p:price="123"
                                     init-method="myinit" destroy-method="mydestroy"/>



  测试代码如下:

  ResourcePatternResolver rpr = new PathMatchingResourcePatternResolver()

  Resource res = rpr.getResource("classpath:spring-context.xml");

  DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

  factory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());

  XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

  reader.loadBeanDefinitions(res);

BeanFactory 加载完毕,只是注册了所有bean 的 beanDefinition,bean 并没有实例化,这就是第一次惩罚的问题,此处与ApplicationContext有 区别的,ApplicationContext在加载完毕以后就会实例化所有的bean,因为在加载ApplicationContext的时候会给所有的bean相应调一次getBean(),以避免第一次惩罚的问题,延迟加载的bean除外。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值