Spring4学习回顾之路06- IOC容器中Bean的生命周期方法
SpringIOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行特定的任务!
Spring IOC容器对Bean的生命周期进行管理的过程:
-通过构造器或者工厂方法创建Bean实例
-为Bean的属性设置值和对其他Bean的引用
-调用Bean的初始化方法
-Bean可以使用了
-当容器关闭了,调用Bean的销毁方法
在Bean的声明中设置init-method和destory-method属性,为Bean指定初始化和销毁方法;如图:
<bean id="student2" class="com.lql.spring03.Student" init-method="init" destroy-method="destory "> <property name="name" value="#{'lql'}"></property> <property name="age" value="#{17}"></property> </bean>
当然,除了上述五个过程之外,Bean的生命周期可以更“丰富”点,于是就有了“Bean后置处理器”;
Bean后置处理器允许在调用初始化方法前后对Bean进行额外的处理;Bean后置处理器对IOC容器里所有的Bean实例逐一处理,而非单一实例。对Bean后置处理器而言,需要实现org.springframework.beans.factory.config.BeanPostProcessor接口,在初始化方法被调用前后,Spring将每个Bean实例分别传递给上述接口的以下两个方法:
package org.springframework.beans.factory.config; import org.springframework.beans.BeansException; public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException; Object postProcessAfterInitialization(Object var1, String var2) throws BeansException; }
Spring IOC容器对Bean的生命周期进行管理的过程:
-通过构造器或者工厂方法创建Bean实例
-为Bean的属性设置值和对其他Bean的引用
-将Bean实例传递给Bean后置处理器的postProcessBeforeInitialization方法
-调用Bean的初始化方法
-将Bean实例传递给Bean后置处理器的postProcessAfterInitialization方法
-Bean可以使用了
-当容器关闭了,调用Bean的销毁方法
案例:建立Bean后置处理器类
package com.lql.spring03; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; /** * @author: lql * @date: 2019.10.26 * Description: * Created with IntelliJ IDEA */ public class MyBeanPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization :" + beanName +", " + bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization:" + beanName +", " + bean); return bean; } }
在xml配置文件中配置Bean后置处理器:
<!--配置bean的后置处理器--> <bean class="com.lql.spring03.MyBeanPostProcessor"></bean>
Student.java
package com.lql.spring03; /** * @author: lql * @date: 2019.10.12 * Description: * Created with IntelliJ IDEA */ public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
测试类:
package com.lql.spring03; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @author: lql * @date: 2019.10.12 * Description: * Created with IntelliJ IDEA */ public class Test { public static void main(String[] args) { ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("scope.xml"); Student student = app.getBean("student", Student.class); System.out.println(student); } }
输出则显示:
postProcessBeforeInitialization :student, Student{name='lql', age=17} postProcessAfterInitialization:student, Student{name='lql', age=17} Student{name='lql', age=17}
但是这样有注入危险,比如更改Bean后置处理器的after方法:更改如下:
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization:" + beanName +", " + bean); Student student = new Student(); student.setName("张三"); return student; }
这样测试的结果是:
postProcessBeforeInitialization :student, Student{name='lql', age=17} postProcessAfterInitialization:student, Student{name='lql', age=17} Student{name='张三', age=0}
还有个需要注意的是:因为Bean后置处理器是处理所以Bean的,所以可以这么修改:
@Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("student".equals(beanName)) { //处理步骤 } System.out.println("postProcessBeforeInitialization :" + beanName +", " + bean); return bean; }
关于BeanPostProcessor的一些说明:
-接口,实现用来作用于Bean后置处理器
-两个方法:Object postProcessBeforeInitialization(Object bean, String beanName):init-method之前被调用
Object postProcessAfterInitialization(Object bean, String beanName):init-method之后被调用
参数 bean: bean 实例本身
参数beanName:IOC容器配置bean的名字
返回值:是实际上返回给用户的那个Bean,但是可以在上面两个方法中修改返回的bean,甚至返回一个新的bean.