(008)spring之BeanPostProcessor的执行时机及作用
BeanPostProcessor是一个接口,有两个方法:postProcessBeforeInitialization、postProcessAfterInitialization,这两个方法每个bean创建都会执行一次。
postProcessBeforeInitialization在属性设置后,init方法执行前执行,postProcessAfterInitialization在属性设置后,init方法执行后执行。请看示例:
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.edu.spring</groupId> <artifactId>spring</artifactId> <version>1.0.0</version> <name>spring</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.2.RELEASE</version> </dependency> </dependencies> </project>
User.java
package com.edu.spring; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; public class User { private ApplicationContext applicationContext; public void init(){ System.out.println("User init()"); } public void show(){ System.out.println("User show(): "+applicationContext); } @Autowired public void setApplicationContext(ApplicationContext applicationContext) { System.out.println("------set()-----"); this.applicationContext = applicationContext; } }
MyConfig.java
package com.edu.spring; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyConfig { @Bean(initMethod="init") public User createUser(){ return new User(); } }
EchoBeanPostProcssor.java
package com.edu.spring; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class EchoBeanPostProcssor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("-------------postProcessBeforeInitialization-------------"+bean.getClass()); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("-------------postProcessAfterInitialization-------------"+bean.getClass()); return bean; } }
App.java
package com.edu.spring; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class App { public static void main(String[] args) { AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext("com.edu.spring"); context.getBean("createUser",User.class).show(); context.close(); } }
运行结果如下:
这两个方法中都不能返回null,否则bean不会创建成功,如下:
EchoBeanPostProcssor.java 中postProcessBeforeInitialization方法返回null
package com.edu.spring; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class EchoBeanPostProcssor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("-------------postProcessBeforeInitialization-------------"+bean.getClass()); if(bean instanceof User){ return null; } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("-------------postProcessAfterInitialization-------------"+bean.getClass()); return bean; } }
运行结果如下:
EchoBeanPostProcssor.java 中postProcessAfterInitialization方法返回null
package com.edu.spring; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class EchoBeanPostProcssor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("-------------postProcessBeforeInitialization-------------"+bean.getClass()); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("-------------postProcessAfterInitialization-------------"+bean.getClass()); if(bean instanceof User){ return null; } return bean; } }
运行结果如下:
BeanPostProcessor接口的作用,可以产生代理对象,实现回调,如添加日志等,如下:
LogUser.java
package com.edu.spring; public class LogUser extends User { public void show(){ System.out.println("LogUser start"); super.show(); System.out.println("LogUser end"); } }
EchoBeanPostProcssor.java
package com.edu.spring; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; @Component public class EchoBeanPostProcssor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("-------------postProcessBeforeInitialization-------------"+bean.getClass()); if(bean instanceof User){ return new LogUser(); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("-------------postProcessAfterInitialization-------------"+bean.getClass()); return bean; } }
运行结果如下:
利用BeanPostProcessor模拟实现注入ApplicationContext对象
SpringContextAware.java
package com.edu.spring; import org.springframework.context.ApplicationContext; public interface SpringContextAware { public void setApplicationContext(ApplicationContext applicationContext); }
Dog.java
package com.edu.spring; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @Component public class Dog implements SpringContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // TODO Auto-generated method stub this.applicationContext=applicationContext; } public void show(){ System.out.println("Dog :"+applicationContext.getClass()); } }
ContextBeanPostProcessor.java
package com.edu.spring; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; @Component public class ContextBeanPostProcessor implements BeanPostProcessor { @Autowired private ApplicationContext applicationContext; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub if(bean instanceof SpringContextAware){ SpringContextAware sa=(SpringContextAware)bean; sa.setApplicationContext(applicationContext); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub return bean; } }
App.java
package com.edu.spring; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class App { public static void main(String[] args) { AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext("com.edu.spring"); context.getBean("dog",Dog.class).show(); context.close(); } }
运行结果如下: