IOC容器中bean的生命周期

一、bean的声明周期

IOC容器在管理bean时,是遵循一整套流程的,bean在IOC容器中从创建到销毁流程如下:

 - 初始化IOC容器
 - 通过构造器或工厂方法创建bean的实例
 - 为bean的属性设置值或者对其它bean的引用
 - 调用bean设置的初始化方法
 - 使用bean
 - 容器关闭时,调用bean的销毁方法,然后关闭容器

下面通过简单实例演示下:
1、首先创建一个bean的类Person

public class Person {

    private String name;

    /*2、调用构造器方法*/
    public Person() {
        System.out.println("hello ..." + name);
    }

    /*bean的初始化方法*/
    /*4、执行bean的初始化方法*/
    public void initMethod(){
        System.out.println("initMethod...");
    }

    /*bean的销毁方法*/
    /*6、执行bean的销毁方法*/
    public void destroyMethod(){
        System.out.println("destroyMethod ...");
    }

    public String getName() {
        return name;
    }

    /*3、为bean的属性赋值*/
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + "]";
    }

}

2、spring的配置文件bean.xml配置如下:

<!--init-method属性指定了调用的初始化方法;destroy-method指定了销毁bean时调用的销毁方法-->
<bean id="person" class="com.lzj.spring.Person"
        init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="lzj"></property>
    </bean>

3、测试方法如下:

public class SpringTest {

    public static void main(String[] args) {

        System.out.println("IOC");
        /*初始化IOC容器*/
        ClassPathXmlApplicationContext ctx = 
                new ClassPathXmlApplicationContext("bean.xml");

        /*5、使用bean*/
        Person person = (Person) ctx.getBean("person");
        System.out.println(person);
        /*7、关闭容器*/
        ctx.close();
    }

}

4、输出结果如下:

IOC-----------

hello ...null
initMethod...
Person [name=lzj]

destroyMethod ...

运行顺序的7个步骤已在上面程序进行标记。

二、创建bean的后置处理器对bean的声明周期影响

创建bean的后置处理器需要实现BeanPostProcessor接口,该接口中有两个方法需要实现:
public Object postProcessAfterInitialization(Object bean, String beanName);
public Object postProcessBeforeInitialization(Object bean, String beanName);
bean为bean的示例对象,beanName为bean的实例对象名,即bean标签中id名。postProcessBeforeInitialization方法在初始化方法initMethod的前调用;postProcessAfterInitialization方法在initMethod初始化方法之后进行调用。如果bean中没有定义初始化方法,则在构造器方法之后调用postProcessBeforeInitialization方法,然后调用postProcessAfterInitialization方法,然后使用bean。
注意: 一旦创建了后置处理器,后置处理器中的两个方法会在每一个bean的初始化方法前后执行,因此若要指定后置处理器只在指定的bean上执行,需要的postProcessAfterInitialization和postProcessBeforeInitialization方法中进行判断。示例如下

1、创建一个bean的类Person(与前面一样)

public class Person {

    private String name;

    /*2、调用构造器方法*/
    public Person() {
        System.out.println("hello ..." + name);
    }

    /*bean的初始化方法*/
    /*4、执行bean的初始化方法*/
    public void initMethod(){
        System.out.println("initMethod...");
    }

    /*bean的销毁方法*/
    /*6、执行bean的销毁方法*/
    public void destroyMethod(){
        System.out.println("destroyMethod ...");
    }

    public String getName() {
        return name;
    }

    /*3、为bean的属性赋值*/
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + "]";
    }

}

2、创建一个后置处理器MyBeanPostProcessor

package com.lzj.spring;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("initMethod方法调用前。。。");
        System.out.println(bean + ":" + beanName);
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("initMethod方法调用后。。。");
        System.out.println(bean + ":" + beanName);
        return bean;
    }

}

3、spring的配置文件bean.xml为

<bean id="person" class="com.lzj.spring.Person">
        <property name="name" value="lzj"></property>
    </bean>

    <bean class="com.lzj.spring.MyBeanPostProcessor"></bean>

4、输出结果如下:

IOC-----------

hello ...null
initMethod方法调用前。。。
Person [name=lzj]:person
initMethod...
initMethod方法调用后。。。
Person [name=lzj]:person
Person [name=lzj]

destroyMethod ...

可见后置处理器中的两个方法分别在initMethod初始化方法的前后进行执行的。bean的声明周期变为:
- 初始化IOC容器
- 通过构造器或工厂方法创建bean的实例
- 为bean的属性设置值或者对其它bean的引用
- 将 Bean 实例传递给 Bean 后置处理器的 postProcessBeforeInitialization 方法
- 调用bean设置的初始化方法
- 将 Bean 实例传递给 Bean 后置处理器的 postProcessAfterInitialization方法
- 使用bean
- 容器关闭时,调用bean的销毁方法,然后关闭容器

注意:当在spring配置文件中定义时,我们在测试文件中获取IOC容器,用getBean方法从容器中获取bean时,获取到的是名字为person的bean。我们可以在后置处理器中的两个方法中进行修改bean,那么用getBean方法从容器中获取到的bean就是修改后的bean了。例如:

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("initMethod方法调用后。。。");
        <!--该方法获取的bean为postProcessBeforeInitialization放回的bean,即为person2,注意,beanName还是在配置文件中配置的id="person"-->
        System.out.println(bean + ":" + beanName);
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("initMethod方法调用前。。。");
        System.out.println(bean + ":" + beanName);
        <!--在初始化方法前,该方法截取了名字为person的bean,然后穿件了一个新的bean person2,用该bean取代了personbean,然后返回person2的bean-->
        if(beanName.equals("person")){
            Person person2 = new Person();
            person2.setName("Jenken");
            bean = person2;
        }
        return bean;
    }

}

测试方法:
public class SpringTest {

public static void main(String[] args) {

    System.out.println("IOC-----------");
    ClassPathXmlApplicationContext ctx = 
            new ClassPathXmlApplicationContext("bean.xml");

    Person person = (Person) ctx.getBean("person");
    System.out.println(person);

    ctx.close();
}

}
输出结果为:

IOC-----------

hello ...null
initMethod方法调用前。。。
Person [name=lzj]:person
hello ...null
person2---
initMethod...
initMethod方法调用后。。。
Person [name=Jenken]:person
Person [name=Jenken]

destroyMethod ...

可见在postProcessBeforeInitialization方法中修改了bean,在postProcessAfterInitialization方法中获取到的bean,以及在后面用getBean方法从容器中获取的bean都是修改过后的bean了。说明,postProcessBeforeInitialization方法中获取已有的Person bean,然后用新的bean去取到了IOC中的person bean。注意,bean的名字还是保持不变的,还是用之前的名字从容器中获取bean就可以了。当然也可以在postProcessAfterInitialization方法中修改bean或者修改bean的属性,然后取代IOC容器中存在的bean,后面用getBean从IOC容器获取的bean依然是修改后的bean。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值