Spring中提供了很多PostProcessor供开发者进行拓展,例如:BeanPostProcessor、BeanFactoryPostProcessor、BeanValidationPostProcessor等一系列后处理器。他们的使用方式大多类似,了解其中一个并掌握他的使用方式,其他的可以触类旁通。
BeanPostProcessor接口作用:
如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。
BeanPostProcessor API:
public interface BeanPostProcessor { /** * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. */ //实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; /** * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * or a custom init-method). The bean will already be populated with property values. */ //实例化、依赖注入、初始化完毕时执行 Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
BeanPostProcessor接口提供了两个供开发者自定义的方法:postProcessBeforeInitialization、postProcessAfterInitialization。
postProcessBeforeInitialization:该方法主要针对spring在bean初始化时调用初始化方法前进行自定义处理。
postProcessAfterInitialization:该方法主要针对spring在bean初始化时调用初始化方法后进行自定义处理。
测试代码:
com.test.model.Cat:
package com.test.model; /** * 测试bean */ public class Cat { private String name; private int age; public void say() { System.out.println("name:" + name); System.out.println("age:" + 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; } }
spring容器中配置cat,和cat的beanPostProcessor:
<!--配置bean并初始化--> <bean id="cat" class="com.test.model.Cat" > <property name="name" value="HelloKitty" /> <property name="age" value="1" /> </bean> <bean id="catBeanPostProcessor" class="com.test.postprocessor.CatBeanPostProcessor" />
com.test.postprocessor.CatBeanPostProcessor:
package com.test.postprocessor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import com.test.model.Cat; /** * 自定义后处理器 */ public class CatBeanPostProcessor implements BeanPostProcessor{ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Cat) { //输出原始属性 Cat cat = (Cat) bean; cat.say(); return bean; } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Cat) { //修改属性值,并返回 Cat cat = (Cat) bean; cat.setName("hello maomi"); cat.setAge(3); return cat; } return bean; } }
IndexController:
package com.cy.controller; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.support.WebApplicationContextUtils; import com.test.model.Cat; @Controller public class IndexController { //到index首页 @RequestMapping(value="index") public String index(HttpServletRequest request){ /** * 访问index同时,从容器中获取已经被初始化之后处理过的cat,打印信息 */ ServletContext servletContext = request.getSession().getServletContext(); ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(servletContext); Cat c = (Cat) ac.getBean("cat"); c.say(); return "index"; } }
观察结果:
容器启动时,输出:
name:HelloKitty
age:1
访问项目http://localhost:8080/demo/index,index链接时,输出:
name:hello maomi
age:3
--------------------------------------------------------------------------------------------------------------------------
可以看到通过后处理器处理过后的bean信息已经改变。最后,看看源码中如何调用自定义实现的。
在初始化bean方法中:AbstractAutowireCapableBeanFactory.java
/** * 初始化bean */ protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { //省略部分无关代码 Object wrappedBean = bean; //初始化前 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { //调用初始化方法初始化bean invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } //初始化后 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } //postProcessBeforeInitialization方法调用 @Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { //调用自定义postProcessBeforeInitialization方法 Object current = beanProcessor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; } //postProcessAfterInitialization方法调用 @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { //自定义postProcessAfterInitialization方法调用 Object current = beanProcessor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }