六、容器中Bean的生命周期

2017-03-05  本文已影响37人  数独题

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

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

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

<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd" >
     <bean id="steelAxe" class="entity.SteelAxe"/>
     
     <!-- 配置ChineseBean,使用init-method="init" -->
     <bean id="chinese" class="entity.Chinese" init-method="init">
        <property name="axe" ref="steelAxe" />
     </bean>
</beans>

输出

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

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

Bean销毁之前的行为:

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

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

协调作用域不同步的Bean:

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

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

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());
     }
}

使用<lookup-method.../>元素需要指定如下两个属性:

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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd" >
    
   
     <bean id="chinese" class="entity.Chinese">
       <!-- Spring只要检测到lookup-method元素,Spring会自动为该元素的name属性所指定的方法提供实现体 -->
        <lookup-method name="getDog" bean="gunDog"/>
     </bean>
     
     <!-- 指定gunDog Bean的作用域为prototype,希望程序每次使用该Bean时都得到不同的实例 -->
     <bean id="gunDog" class="entity.GunDog" scope="prototype">
        <property name="name" value="旺财"/>
     </bean>
</beans>

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

上一篇下一篇

猜你喜欢

热点阅读