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

图 1 Bean 的生命周期图
下面我们对其中部分步骤进行分析:
BeanNameAware;如果Bean实现了BeanNameAware接口,Spring将配置文件中 Bean的id传给setBeanName()方法。
public class bean implements BeanNameAware{@Overridepublic void setBeanName(String beanName) {System.out.println("第三步:setBeanName方法");}}
BeanFactoryAware;如果Bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到Bean中。
public class bean implements ApplicationContextAware{@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("第四步:setApplicationContext方法");}}
InitializingBean;如果Bean实现了InitializingBean接口,Spring将调用它的afterPropertiesSet方法。
public class bean implements InitializingBean{@Overridepublic 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的配置文件中添加Bean的init-method和destory-method属性:
DisposableBean。如果Bean实现DisposableBean接口,则执行destroy方法。
public class bean implements DisposableBean{@Overridepublic 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*/@Overridepublic 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*/@Overridepublic Object postProcessAfterInitialization(Object obj, String beanName) throws BeansException {System.out.println("第八步:postProcessAfterInitialization方法"+beanName);return obj;}}
后处理Bean一般不由Bean本身实现,而是独立存在,因此需要注册到Spring容器中:
请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,结合Bean的生命周期将User类Bean实例的name属性值修改为Jack,并把周期过程输出如下(图中的黑色字体为过程,红色字体为说明):

图 2 周期过程图
右侧代码文件共中有配置文件、MyBeanPostProcessor类、Task类、User类需要根据提示补充,后台会自动创建Task对象调用getBean()方法获取Bean输出周期过程。
补充完代码后,点击测评,平台会对你编写的代码进行测试,当你的结果与预期输出一致时,即为通过。
预期输出:
设置对象属性setUsername()调用BeanNameAware的setBeanName()方法初始化Bean之前的处理,此时我的名字:User{username='Tom'}对初始化之后的Bean进行处理,将Bean的成员变量的值修改了设置对象属性setUsername()User{username='Jake'}
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="user" class="com.educoder.step2.User">
- <property name="username" value="Tom"></property>
- </bean>
- <!-- 配置后处理器 -->
- <bean class="com.educoder.step2.MyBeanPostProcessor"></bean>
- </beans>
MyBeanPostProcessor.java
- package com.educoder.step2;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanPostProcessor;
- public class MyBeanPostProcessor implements BeanPostProcessor {
- //对初始化之后的Bean进行处理
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanname) throws BeansException {
- /********** Begin **********/
- System.out.println("对初始化之后的Bean进行处理,将Bean的成员变量的值修改了");
- User stu = null;
- if("user".equals(beanname) || bean instanceof User) {
- stu = (User) bean;
- stu.setUsername("Jake");
- return stu;
- }
- return bean;
- /********** End **********/
- }
- //对初始化之前的Bean进行处理
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanname) throws BeansException {
- /********** Begin **********/
- System.out.println("初始化Bean之前的处理,此时我的名字:"+bean);
- return bean;
- /********** End **********/
- }
- }
User.java
- package com.educoder.step2;
- import org.springframework.beans.factory.BeanNameAware;
- public class User implements BeanNameAware {
- private String username;
- public User() {}
- //注入username属性
- public void setUsername(String username) {
- /********** Begin **********/
- System.out.println("设置对象属性setUsername()");
- this.username = username;
- /********** End **********/
- }
- //实现BeanNameAware接口 并重写setBeanName方法
- @Override
- public void setBeanName(String name) {
- /********** Begin **********/
- System.out.println("调用BeanNameAware的setBeanName()方法" );
- /********** End **********/
- }
- //返回字符串:User{name='属性值'}
- @Override
- public String toString() {
- /********** Begin **********/
- return "User{" +
- "username='" + username + '\'' +
- '}';
- /********** End **********/
- }
- }
Task.java
- package com.educoder.step2;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Task {
- //获取User类Bean实例
- public User getBean(){
- /********** Begin **********/
- ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
- User bean = (User) app.getBean("user");
- return bean;
- /********** End **********/
- }
- }
