六、容器中Bean的生命周期

依赖关系注入之后的行为:

Spring提供两种方式在Bean的全部属性设置成功后执行特定的行为:

  • 使用init-method属性。
  • 实现InitializingBean接口。
    第一种方式:使用init-method属性指定某个方法在Bean全部依赖关系设置结束后自动执行。使用这种方式不需要讲代码与Spring的接口耦合在一起,代码污染小。
    第二种方式:让Bean类实现initlializingBean接口,该接口提供一个方法void afterPropertiesSet() thorows Exception;Spring会在为该Bean注入依赖关系之后,调用该Bean所实现的afterPropertiesSet()方法。

Chinese.java

package entity;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import inter.Axe;
import inter.Persion;

public class Chinese implements Persion,InitializingBean,BeanNameAware,ApplicationContextAware {

    private Axe axe;
    @Override
    public void setApplicationContext(ApplicationContext arg0)
            throws BeansException {
        System.out.println("======setApplicationContext=======");
        
    }

    public Chinese()
    {
        System.out.println("Spring实例化主调Bean:Chinese实例...");
    }
    @Override
    public void setBeanName(String arg0) {
        // TODO Auto-generated method stub
        System.out.println("=============setBeanName===============");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("正在执行初始化方法afterPropertiesSet.....");
    }

    @Override
    public void useAxe() {
        // TODO Auto-generated method stub
        System.out.println(axe.chop());
    }
    public void setAxe(Axe axe)
    {
        System.out.println("Spring调用setAxe()执行依赖注入...");
        this.axe=axe;
    }

    public void init()
    {
        System.out.println("正在执行初始化方法init....");
    }
}

beans.xml



     
     
     
     
        
     

输出

Spring实例化主调Bean:Chinese实例...
Spring调用setAxe()执行依赖注入...
=============setBeanName===============
======setApplicationContext=======
正在执行初始化方法afterPropertiesSet.....
正在执行初始化方法init....
钢斧砍柴真快!

如果某个类实现了Initializing接口,当该Bean所有的依赖关系被设置完成后,Spring容器会自动调用该Bean实例的setPropertiesSet()方法;其执行结果与采用init-method属性指定生命周期一样。但现实Initializing接口污染代码,是低侵入式设计。

Bean销毁之前的行为:

Spring提供了两种定制Bean实例销毁之前的特定行为:

  • 使用destroy-method属性。
  • 实现DisposableBean接口。
    第一种方式:使用destroy-method属性指定某个方法在Bean销毁之前自动被执行,使用这种方式不需将代码与Spring的接口耦合在一起,代码污染低。
    第二种方式:让Bean类实现DisposableBean接口,实现该接口提供的方法void destroy() throws Exception。

配置文件与实例化之后的beans.xml文件类似。

协调作用域不同步的Bean:

当singleton作用域的Bean依赖于prototype作用域的Bean时,会产生不同步的现象,解决该问题有两种思路:

  • 放弃依赖注入:singleton作用域的Bean每次需要prototype作用域的Bean时,主动向容器请求新的Bean实例,即可保证每次注入的prototype Bean实例都是最新的实例。
  • 利用方法注入:方法注入通常采用lookup方法注入。

为了使用lookup方法注入,大致需要两步

  • 将调用者Bean的实现类定义为抽象类,并定义一个抽象方法来获取被依赖的Bean。
  • 元素中添加子元素让Spring为调用者Bean的实现类实现指定的抽象方法。

Chinese.java

public abstract class Chinese implements Persion
{
     private Dog dog;
     //定义抽象方法,该方法用于获取被依赖的Bean
     public abstract Dog getDog();
     public void hunt()
     {
           System.out.println("我带着"+getDog()+"出去打猎");
           System.out.println(getDog().run());
     }
}

使用元素需要指定如下两个属性:

  • name:指定需要让Spring实现的方法。
  • bean:指定Spring实现该方法的返回值。

beans.xml



    
   
     
       
        
     
     
     
     
        
     

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

你可能感兴趣的:(六、容器中Bean的生命周期)