spring学习之---容器中Bean的生命周期

spring可以管理singleton作用域的Bean的生命周期,spring可以精确地知道该Bean何时被创建、何时被初始化完成、容器何时准备销毁该Bean实例。
对于prototype作用域的Bean,spring容器仅仅负责创建,当容器创建了Bean实例之后,Bean实例完全交给客户端代码管理,容器不再跟踪其生命周期,spring无法管理prototype作用域的Bean。

1.依赖关系注入之后的行为

spring提供两种方式在Bean全部属性设置成功执行特定行为。

  • 使用init-method属性。
  • 实现InitializingBean接口。该接口提供一个方法:void afterPropertiesSet() throws Exception;
    public class Chinese implements InitializingBean{
        public void init(){
            System.out.println("正在执行初始化方法init");
        }
        public void afterPropertiesSet() throws Exception{
            System.out.println("正在执行初始化方法afterPropertiesSet...");
        }
    }

    "chinese" class="" init-method="init"/>

只要配置文件使用init-method属性指定该方法是一个”生命周期方法。”
如果同时采用了两种方式指定初始化方法:先执行InitializingBean接口中定义的方法,然后执行ini-method属性指定的方法。

2.Bean销毁之前的行为

spring也提供两种方式定制Bean实例销毁之前的特定行为,这两种方式如下:

  • 使用destroy-method属性。
  • 实现DisposableBean接口。该接口提供void destroy() throws Exception;
    使用方式和初始化的方式一样。

singleton作用域的Bean通常会随容器的关闭而销毁,在基于Web的ApplicationContext实现中,系统已经提供了相应的代码保证关闭Web应用时恰当地关闭spring容器。对于处于一个非Web应用的环境中,为了让spring容器优雅地关闭,并调用singleton Bean上相应析构回调方法,则需要在JVM里注册一个关闭钩子,这样就可保证spring容器被恰当关闭,且自动执行singleton Bean实例的析构回调方法。
为了注册关闭钩子,只需要调用在AbstractApplicationContext中提供的registerShutdownHook()方法即可。

    main{
        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        ...
        //为spring容器注册关闭钩子
        ctx.registerShutdownHook();
    }

spring容器中Bean实例的生命周期:创建实例->注入依赖关系->调用afterPropertiesSet->调用init-method方法->对外提供服务->调用destroy->调用destroy-method方法->Bean实例被销毁

3.协调作用域不同步的Bean

当singleton作用域的Bean依赖prototype作用域的Bean时,spring容器会在初始化singleton作用域的Bean之前,先创建被依赖的prototype Bean,然后才初始化singleton Bean,并将prototype Bean注入singleton Bean,这样就相当于singleton Bean把它所依赖的prototype Bean变成了singleton行为。
当singleton作用域的Bean依赖于prototype作用域的Bean时,会产生不同步的现象,解决方案:
- 放弃依赖注入
- 利用方法注入

方法注入通常使用lookup方法注入,使用lookup方法注入可以让spring容器重写容器中Bean的抽象或具体方法,返回查找容器中其他Bean的结果,被查找的Bean通常是一个non-singleton Bean(尽管也可以是一个singleton的)。spring通过使用JDK动态代理或cglib库修改客户端的二进制码,从而实现上述要求。

为了使用lookup方法注入,需要如下两步:
1. 将调用者Bean的实现类定义为抽象类,并定义一个抽象方法来获取被依赖的Bean。
2. 在元素中添加子元素让spring为调用者Bean的实现类实现指定的抽象方法。

  • name:指定需要让spring实现的方法。
  • bean:指定spring实现该方法的返回值。
    public abstract class Chinese{
        private Dog dog;
        public abstract Dog getDog();
        public void hunt(){
            System.out.println(getDog().run());
        }
    }

    "chinese" class="">
        "getDog" bean="gunDog"/>
    
    "gunDog" class="" scope="prototype">

spring会采用运行时动态增强的方式来实现元素所指定的抽象方法,如果目标抽象类实现过接口,spring会采用JDK动态代理来实现该抽象类,并为之实现抽象方法;如果没有实现接口,则采用cglib实现该抽象类。

你可能感兴趣的:(spring)