1、簡(jiǎn)介
BeanPostProcessor和BeanFactoryProcessor是Spring中很重要的了兩個(gè)接口。我們先來(lái)看看Spring的文檔中對(duì)BeanPostProcessor的定義:
The BeanPostProcessor interface defines callback methods that you can
implement to provide your own (or override the container’s default)
instantiation logic, dependency-resolution logic, and so forth. If you want
to implement some custom logic after the Spring container finishes
instantiating, configuring,and initializing a bean, you can plug in one or
more BeanPostProcessor implementations.
BeanPostProcessor 接口定義了一個(gè)你可以自己實(shí)現(xiàn)的回調(diào)方法,來(lái)實(shí)現(xiàn)你自己的實(shí)例化邏輯、依賴(lài)解決邏輯等,如果你想要在Spring完成對(duì)象實(shí)例化、配置、初始化之后實(shí)現(xiàn)自己的業(yè)務(wù)邏輯,你可以補(bǔ)充實(shí)現(xiàn)一個(gè)或多個(gè)BeanPostProcessor的實(shí)現(xiàn)。
我們?cè)賮?lái)看一下文檔那個(gè)中對(duì)BeanFactoryPostProcessor的描述:
The semantics of this interface are similar to those of the
BeanPostProcessor, with one major difference:BeanFactoryPostProcessor
operates on the bean configuration metadata; that is, the Spring IoC
container allows a BeanFactoryPostProcessor to read the configuration
metadata and potentially change it before the container instantiates any
beans other than BeanFactoryPostProcessors.
BeanFactoryPostProcessor的定義和BeanPostProcessor相似,有一個(gè)最主要的不同是:BeanFactoryPostProcessor可以對(duì)bean的配置信息進(jìn)行操作;更確切的說(shuō)Spring IOC容器允許BeanFactoryPostProcessor讀取配置信息并且能夠在容器實(shí)例化任何其他bean(所有的實(shí)現(xiàn)了BeanFactoryPostProcessor接口的類(lèi))之前改變配置信息
2、BeanPostProcessor和BeanFactoryProcessor的定義
BeanPostProcessor有兩個(gè)方法:
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.
* The returned bean instance may be a wrapper around the original.
* @param bean bean的實(shí)例
* @param beanName bean的name
* @return 返回處理過(guò)后的bean,可以是最初的Bean或者是包裝后的Bean;
* 如果返回null,后續(xù)的BeanPostProcessor不會(huì)被執(zhí)行
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
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.
* The returned bean instance may be a wrapper around the original.
* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
* instance and the objects created by the FactoryBean (as of Spring 2.0). The
* post-processor can decide whether to apply to either the FactoryBean or created
* objects or both through corresponding {@code bean instanceof FactoryBean} checks.
* <p>This callback will also be invoked after a short-circuiting triggered by a
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other BeanPostProcessor callbacks.
* @param bean bean的實(shí)例
* @param beanName bean的name
* @return 返回處理過(guò)后的bean,可以是最初的Bean或者是包裝后的Bean;
* 如果返回null,后續(xù)的BeanPostProcessor不會(huì)被執(zhí)行
* {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
我們可以看到注釋postProcessBeforeInitialization方法是在所有的bean的InitializingBean的afterPropertiesSet方法之前執(zhí)行而postProcessAfterInitialization方法則是在所有的bean的InitializingBean的afterPropertiesSet方法之后執(zhí)行的。
而B(niǎo)eanFactoryPOSTProcessor只有一個(gè)方法:
*/
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
我們可以看到注釋中寫(xiě)到的:postProcessBeanFactory可以在BeanFactory完成實(shí)例化后修改容器內(nèi)部的BeanFactory。這時(shí)候所有的bean都被加載,但是沒(méi)有bean被初始化。這就允許BeanFactoryPOSTProcessor重寫(xiě)或者添加配置,甚至可以提前初始化bean。
好了,說(shuō)了這么多,也許大家對(duì)BeanPostProcessor和BeanFactoryProcessor還是有些迷惑,我們來(lái)看一個(gè)例子就能明白了:
3、示例
我們先創(chuàng)建一個(gè)類(lèi)實(shí)現(xiàn)BeanPostProcessor:
public class TestBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "-->" + "TestBeanPostProcessor->postProcessBeforeInitialization");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName + "-->" + "TestBeanPostProcessor->postProcessAfterInitialization");
return bean;
}
}
在創(chuàng)建一個(gè)類(lèi)實(shí)現(xiàn)BeanFactoryPostProcessor:
public class TestBeanFactoryPostPorcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("TestBeanFactoryPostPorcessor->postProcessBeanFactory");
}
}
然后創(chuàng)建一個(gè)普通的bean,實(shí)現(xiàn)了InitializingBean和DisposableBean接口:
public class TestBean implements InitializingBean, DisposableBean{
private String name;
private int age;
public TestBean() {
System.out.println("TestBean->constrcutor");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("TestBean->setter");
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
System.out.println("TestBean->setter");
this.age = age;
}
public void destroy() throws Exception {
System.out.println("TestBean->destroy");
}
public void afterPropertiesSet() throws Exception {
System.out.println("TestBean->afterPropertiesSet");
}
}
然后在xml文件中注冊(cè)這三個(gè)bean:
<bean id="testBeanPostProcessor" class="wbx.test_spring_noweb.beans.TestBeanPostProcessor"></bean>
<bean id="testBeanFactoryPostProcessor" class="wbx.test_spring_noweb.beans.TestBeanFactoryPostPorcessor"></bean>
<bean id="testBean" class="wbx.test_spring_noweb.beans.TestBean">
<property name="name" value="丑星星"></property>
<property name="age" value="18"></property>
</bean>
最后寫(xiě)測(cè)試類(lèi)運(yùn)行:
public class Test {
public static void main(String[] args) {
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("classpath:wbx/test_spring_noweb/beans.xml");
TestBean testBean = (TestBean)context.getBean("testBean");
context.destroy();
}
}
我們可以看到控制臺(tái)的運(yùn)行結(jié)果,這里截圖一部分:

我們可以看到Bean的生命周期:
1、解析xml文件,解析出BeanDefinition
2、Spring容器創(chuàng)建BeanFactoryPostProcessor實(shí)例
3、調(diào)用BeanFactoryPostProcessor的postProcessBeanFactory方法
4、Spring容器創(chuàng)建BeanPostProcessor實(shí)例
5、在需要?jiǎng)?chuàng)建其他Bean實(shí)例的時(shí)候創(chuàng)建其他Bean
6、調(diào)用Bean的構(gòu)造方法
7、調(diào)用Bean的setter方法為Bean屬性賦值
8、調(diào)用BeanPostProcessor的postProcessBeforeInitialization方法
9、調(diào)用InitializingBean的afterPropertiesSet方法
10、調(diào)用BeanPostProcessor的postProcessAfterInitialization方法
11、容器銷(xiāo)毀的時(shí)候調(diào)用DisposableBean的destroy方法
4、BeanPostProcessor在Spring內(nèi)部的使用舉例
我們都知道,當(dāng)一個(gè)Bean實(shí)現(xiàn)了OoXxAware接口后,Spring就會(huì)自動(dòng)將OoXx對(duì)象注入,例如:一個(gè)Bean實(shí)現(xiàn)了ApplicationContextAware接口,Spring會(huì)嘗試將ApplicationContext對(duì)象注入到這個(gè)Bean中,這是怎么實(shí)現(xiàn)的呢?
當(dāng)Spring容器初始化時(shí),會(huì)先解析Bean的定義,將定義解析成BeanDefinition對(duì)象,并且由BeanDefinitionHolder包裝一層,注冊(cè)到BeanFactory中。我們可以看一下容器刷新的方法(AbstractApplicationContext類(lèi)中的):
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
解析Bean在ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();中完成。有興趣的同學(xué)可以自己看一下。然后調(diào)用postProcessBeanFactory(beanFactory);方法,我們看一下這個(gè)方法:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
這個(gè)方法其實(shí)就是為BeanFactory初始化一些屬性的值。
我們可以看到有一個(gè)行代碼:beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
ApplicationContextAwareProcessor實(shí)現(xiàn)了BeanPostProcessor接口。這行代碼將ApplicationContextAwareProcessor注冊(cè)到beanFactory的BeanPostProcessor集合中。我們?cè)賮?lái)看一下ApplicationContextAwareProcessor的部分代碼:
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean);
return null;
}
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
ApplicationContextAwareProcessor會(huì)先判斷bean是否實(shí)現(xiàn)了Aware接口,如果是,再根據(jù)Aware的類(lèi)型來(lái)調(diào)用相應(yīng)的定義的接口來(lái)給Bean注入相應(yīng)的資源。
5、總結(jié)
BeanPostProcessor和BeanFactoryProcessor的區(qū)別是重點(diǎn),也是面試的時(shí)候經(jīng)??嫉摹8匾氖且粋€(gè)Ben的生命周期,希望大家可以重點(diǎn)看一下第三部分的示例,好好理解Bean的生命周期!