Spring 的 Bean 管理 第2关:bean 的生命周期

28 篇文章 11 订阅

目录

任务描述

相关知识

Bean 的生命周期

后处理器

编程要求

测试说明

 参考答案

applicationContext.xml

MyBeanPostProcessor.java

Student.java 

Task.java

运行截图


任务描述

本关任务:结合bean的生命周期修改beanname属性值。

相关知识

为了完成本关任务,你需要掌握 Bean 生命周期的11个步骤。

Bean 的生命周期

在传统的 Java 应用中,bean的生命周期非常简单,使用new关键字对bean进行实例化,该bean就可以使用了。当bean不再被使用后 Java 将自动进行垃圾回收。

相比之下, Spring 容器中bean的生命周期就比较细致。理解 Spring bean 的生命周期非常重要,因为你或许要利用 Spring 提供的扩展点来自定义bean的创建过程。

下图展示了 Spring 中 bean 生命周期的11个步骤:

下面我们对其中部分步骤进行分析:

  • 第三步:BeanNameAware

如果bean实现了 BeanNameAware 接口, Spring 将配置文件中beanid传给setBeanName()方法。

public class bean implements BeanNameAware{
    @Override
    public void setBeanName(String beanName) {
        System.out.println("第三步:setBeanName方法");
    }
}
  • 第四步:BeanFactoryAware

如果bean实现了 ApplicationContextAware 接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中。

public class bean implements ApplicationContextAware{
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("第四步:setApplicationContext方法");
    }
}
  • 第六步:InitializingBean

如果bean实现了 InitializingBean 接口,Spring 将调用它的afterPropertiesSet方法。

public class bean implements InitializingBean{
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("第六步:afterPropertiesSet方法");
    }
}
  • 第七、十一步:指定 Bean 的初始化和销毁方法

bean自定义的初始化和销毁方法如下:

public class bean{
    public void init(){
        System.out.println("第七步:init方法");
    }
    public void destory(){
        System.out.println("第十一步:destory方法");
    }
}

若要自定义的初始化、销毁方法被使用,则需要在 Spring 的配置文件中添加beaninit-methoddestory-method属性:

<bean id="bean" class="educoder.bean" init-method="init" destroy-method="destory"></bean>
  • 第十步:DisposableBean

如果bean实现 DisposableBean 接口,则执行destroy方法。

public class bean implements DisposableBean{
    @Override
    public void destroy() throws Exception {
        System.out.println("第十步:DisposableBean的destory方法");
    }
}

注意:执行销毁的时候,必须手动调用close方法关闭工厂,并且只对scope="singleton"有效。

后处理器

  • 第五、八步:BeanPostProcessor

BeanPostProcessor 称为后处理器。如果存在bean实现 BeanPostProcessor 接口,则第五步执行postProcessBeforeInitialization方法、第八步执行postProcessAfterInitialization方法。

Spring 通过接口反射预先知道,当 Spring 容器创建任何bean**时,这些后处理器都会发生作用**。

下面例子在任何bean的初始化之前和之后输出方法名及该bean的名称。你还可以在初始化bean的前后实现更复杂的逻辑,因为你有这两个访问内置bean对象的后置处理程序的方法。

public class afterBean implements BeanPostProcessor {
    /** 
     * 对初始化之前的Bean进行处理
     * @param bean  即将初始化的bean
     * @param beanname   bean的名称
     * @return   返回给用户的那个bean,可以修改bean也可以返回一个新的bean
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object obj, String beanName) throws BeansException {
        System.out.println("第五步:postProcessBeforeInitialization方法"+beanName);
        return obj;
    }
    /**
     * 对初始化之后的Bean进行处理
     * @param bean   即将初始化的bean
     * @param beanname   bean的名称
     * @return   返回给用户的那个bean,可以修改bean也可以返回一个新的bean
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object obj, String beanName) throws BeansException {
        System.out.println("第八步:postProcessAfterInitialization方法"+beanName);
        return obj;
    }
}

后处理bean一般不由bean本身实现,独立存在,因此需要注册到 Spring 容器中:

<bean class="educoder.afterBean"></bean>

编程要求

在右侧编辑器补充代码,结合bean的生命周期将beanname属性值修改为Jack,并在相应周期方法中输出如下信息,实现过程及解释如下图:

测试说明

平台将对你编写的代码进行测试:

预期输出:

 参考答案

applicationContext.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id ="dog" class="educoder.Dog"></bean>
	<bean id="student" class="step2.Student">
		<property name="name" value="Tom"></property>
	</bean>
    
	<bean class="step2.MyBeanPostProcessor"></bean>
</beans>

MyBeanPostProcessor.java

package step2;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**********   Begin   **********/
public class MyBeanPostProcessor implements BeanPostProcessor{
    
	@Override
    public Object postProcessAfterInitialization(Object bean, String beanname) throws BeansException {
        Student stu= null; 
	    System.out.println("对初始化之后的Bean进行处理,将Bean的成员变量的值修改了");
		if("name".equals(beanname)||bean instanceof Student){
		stu=(Student) bean;
		stu.setName("Jack");
		} 
        return  stu;
    }
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanname) throws BeansException {
        System.out.println("初始化Bean之前的处理,此时我的名字:"+bean);
        return bean;
    }
}
/**********   End   **********/

Student.java 

package step2;

import org.springframework.beans.factory.BeanNameAware;

/**********   Begin   **********/
public class Student implements BeanNameAware{
    private String name;
    public Student() {}
    
    public void setName(String name) {
		System.out.println("设置对象属性setName()");
        this.name = name;
    }

    //实现BeanNameAware接口  并重写setBeanName方法
	@Override
    public void setBeanName(String beanName){
		System.out.println("调用BeanNameAware的setBeanName()方法");
	}
    
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}
/**********   End   **********/

Task.java

package step2;

import educoder.Dog;
import step2.MyBeanPostProcessor;
import step2.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Task {
    public Student getBean(){
        /**********   Begin   **********/
		ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
		Student student = app.getBean("student",Student.class);
        return student;
        /**********   End   **********/
    }
}

运行截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

于建章

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值