Spring框架提供了BeanPostProcessor接口,该接口暴露了两个方法postProcessBeforeInitialization(Object bean,String beanName)
和postProcessAfterInitialization(Object bean,String beanName).其中第一参数是经过实例化的bean实例,第二个参数是该bean在
spring IOC容器中的唯一标识.
通过实现BeanPostProcessor接口的postProcessBeforeInitialization和postProcessAfterInitialization方法,我们可以做很多有意义的
事情.postProcessBeforeInitialization方法的调用时机是在bean实例化并装配完毕之后,在调用初始化方法之前;而第二方法调用的时机
是在初始化方法调用之后.为了便于理解,我画了一张图:
通过上图可知,我们可以定义多个BeanPostProcessor接口的实现类,多个实现类直接以责任链的方式依次执行.
一般情况下BeanPostProcessor的实现类还会实现org.springframework.core.Ordered接口,Ordered接口的定义了getOrder方法,该方
法的返回值代表该BeanPostProcessor实现类的执行时机(数字越小,越先执行)
我们下面写一段例子程序,以上图为原本.程序中会定义三个BeanPostProcessor,三个的作用如下:
红色:LogRecorder,记录日志
蓝色:TimeRecoder,记录执行时间记录
紫色:PermissionCheck,权限检查
1.新建com.tutorialspoint.post_processor包,并在包中新建HelloWorld.java类,类的内容如下:
package com.tutorialspoint.post_processor; public class HelloWorld { public HelloWorld(){ System.out.println("constructor invoked ... "); } private String message; public void setMessage(String message){ System.out.println("set method invoked ... "); this.message = message; } public void getMessage(){ System.out.println("Your Message : " + message); } public void init(){ System.out.println("init method invoked ... "); } public void destroy(){ System.out.println("destroy method invoked ... "); } }
2.在包com.tutorialspoint.post_processor中新建上述三个BeanPostProcessor的实现类,三个类的内容分别如下:
LogRecorder.java
package com.tutorialspoint.post_processor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.Ordered; public class LogRecorder implements BeanPostProcessor,Ordered { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { //初始化方法调用之后会回调该方法,在这里可以根据实际需求进行编码。 System.out.println("Log Info:"+beanName+" has been initailized"); return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { //初始化方法调用之前调用该方法. System.out.println("Log Info:"+beanName+" is going to be initailized"); return bean; } //实现该方法用于指明该BeanPostProcessor的执行时机 @Override public int getOrder() { return 1; } }
TimeRecoder.java
package com.tutorialspoint.post_processor; import java.util.Date; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.Ordered; public class TimeRecoder implements BeanPostProcessor,Ordered{ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName+" has been initilized,time now is "+new Date()); return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName+" is going to be initilized,time now is "+new Date()); return bean; } @Override public int getOrder() { return 2; } }
PermissionCheck.java
package com.tutorialspoint.post_processor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.Ordered; public class PermissionCheck implements BeanPostProcessor,Ordered { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName+" has been initailized,permissions checked... "); return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println(beanName+" is going to be initailized,begin to check permissions ... "); return bean; } @Override public int getOrder() { return 3; } }
3.在src目录下新建post_processor.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-3.0.xsd"> <bean id="helloWorld" class="com.tutorialspoint.post_processor.HelloWorld" destroy-method="destroy" init-method="init"> <property name="message" value="Hello World!"></property> </bean> <!-- spring容器会检测到实现了BeanPostProcessor接口的bean,并在适当的时机调用适当的方法 --> <bean name="logRecorder" class="com.tutorialspoint.post_processor.LogRecorder"></bean> <bean name="timeRecoder" class="com.tutorialspoint.post_processor.TimeRecoder"></bean> <bean name="permissionCheck" class="com.tutorialspoint.post_processor.PermissionCheck"></bean> </beans>
4.在com.tutorialspoint.post_processor包中新建MainApp.java,内容如下:
package com.tutorialspoint.post_processor; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("post_processor.xml"); HelloWorld hw = (HelloWorld)ctx.getBean("helloWorld"); hw.getMessage(); ctx.registerShutdownHook(); } }
5.运行程序,检查结果:
仔细分析运行结果,跟我们预期是一致的!