|
目录
任务描述
相关知识
Bean 的生命周期
后处理器
编程要求
测试说明
?参考答案
applicationContext.xml
MyBeanPostProcessor.java
Student.java?
Task.java
运行截图
任务描述
本关任务:结合bean的生命周期修改bean的name属性值。
相关知识
为了完成本关任务,你需要掌握 Bean 生命周期的11个步骤。
Bean 的生命周期
在传统的 Java 应用中,bean的生命周期非常简单,使用new关键字对bean进行实例化,该bean就可以使用了。当bean不再被使用后 Java 将自动进行垃圾回收。
相比之下, Spring 容器中bean的生命周期就比较细致。理解 Spring bean 的生命周期非常重要,因为你或许要利用 Spring 提供的扩展点来自定义bean的创建过程。
下图展示了 Spring 中 bean 生命周期的11个步骤:

下面我们对其中部分步骤进行分析:
如果bean实现了 BeanNameAware 接口, Spring 将配置文件中bean的id传给setBeanName()方法。
public class bean implements BeanNameAware{
@Override
public void setBeanName(String beanName) {
System.out.println("第三步:setBeanName方法");
}
}
如果bean实现了 ApplicationContextAware 接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中。
public class bean implements ApplicationContextAware{
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("第四步:setApplicationContext方法");
}
}
如果bean实现了 InitializingBean 接口,Spring 将调用它的afterPropertiesSet方法。
public class bean implements InitializingBean{
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("第六步:afterPropertiesSet方法");
}
}
bean自定义的初始化和销毁方法如下:
public class bean{
public void init(){
System.out.println("第七步:init方法");
}
public void destory(){
System.out.println("第十一步:destory方法");
}
}
若要自定义的初始化、销毁方法被使用,则需要在 Spring 的配置文件中添加bean的init-method和destory-method属性:
<bean id="bean" class="educoder.bean" init-method="init" destroy-method="destory"></bean>
如果bean实现 DisposableBean 接口,则执行destroy方法。
public class bean implements DisposableBean{
@Override
public void destroy() throws Exception {
System.out.println("第十步:DisposableBean的destory方法");
}
}
注意:执行销毁的时候,必须手动调用close方法关闭工厂,并且只对scope="singleton"有效。
后处理器
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的生命周期将bean的name属性值修改为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 **********/
}
}
运行截图

|