首先下面是我的Bean
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.verify.constant;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import java.beans.PropertyDescriptor;
/**
* TODO
*
* @author linjiedeng
* @date 17/5/8 下午10:47
* @since TODO
*/
public class StudentService implements BeanPostProcessor, InitializingBean, BeanFactoryPostProcessor, BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
private ClassLoader classLoader;
private BeanFactory beanFactory;
private String name;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader; //实现BeanClassLoaderAware接口可以获取到对应的classLoader
System.out.println("set bean class loader");
System.out.println(classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory; //实现BeanFactoryAware接口获取该Bean的beanFactory
System.out.println("set bean factory");
System.out.println(beanFactory);
}
@Override
public void setBeanName(String name) {
this.name = name; //实现BeanNameAware接口获取该Bean的名字
System.out.println("set bean name");
System.out.println(name);
}
public void initMethod() {
System.out.println("init method");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization");
return bean;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("postProcessBeanFactory");
}
public void read() {
System.out.println("Student service read");
}
}
bean的配置文件applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="studentService" class="com.verify.constant.StudentService" init-method="initMethod"/>
</beans>
测试代码如下:
@Test
public void test2() {
ClassPathResource resource = new ClassPathResource("applicationContext.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);
StudentService studentService = (StudentService)factory.getBean("studentService");
studentService.read();
}
测试代码执行后,其他方法都执行了,但是唯独BeanPostProcessor接口的两个方法postProcessBeforeInitialization和postProcessAfterInitialization以及
BeanFactoryPostProcessor接口的方法没有执行,这我就有点疑惑了,这是咋回事?其实这两个接口应该是在bean初始化的过程中被调用,是在AbstractAutowireCapableBeanFactory接口的initializeBean初始化方法中被调用的,代码如下:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//执行BeanPostProcessor扩展点的PostProcessBeforeInitialization进行修改实例化Bean
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//调用Bean的初始化方法,这个初始化方法是在BeanDefinition中通过定义init-method属性指定的
//同时,如果Bean实现了InitializingBean接口,那么这个Bean的afterPropertiesSet实现也不会被调用
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()) {
//执行BeanPostProcessor扩展点的PostProcessAfterInitialization进行修改实例化Bean
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
initializeBean方法是Bean的初始化方法,在该初始化方法中会调用Bean的一些初始化方法,比如如下方法:
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
即只要Bean实现了BeanNameAware接口,这里就会帮你调用,BeanClassLoaderAware和BeanFactory接口同样如此,上述我的代码中就实现了这三个接口,启动的过程中都被调用了,再实现的方法中可以获取这些信息,并存储。
再比如如下方法:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
这里其实是如果Bean实现了BeanPostProcessor接口,这里就会调用bean实现的postProcessBeforeInitialization方法,这是在bean的真正初始化之前被调用
对应的BeanPostProcessor接口的另外一个方法,是在bean的初始化之后被调用,如下:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
真正的初始化是在如下方法:
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet(); //启动afterPropertiesSet,afterPropertiesSet是InitializingBean接口的方法
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName(); //获取用户自定义的初始化方法
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd); //调用自定义的初始化方法
}
}
}
可以看到,上述代码实际上是在调用Bean实现的initializingBean接口的afterPropertiesSet方法来初始化Bean,接下来还调用了用户自定义的init-method方法,可以看到上面我的applicationContext.xml配置文件中配置的有一个initMethod方法,这就是自定义的初始化方法,这个方法也是在这里被调用的
好,代码分析到这,也可以看到了,既然这里初始化的时候调用了BeanPostProcessor的那两个方法,但是我的测试代码为什么没有执行这两个方法呢?
其实可以看到真正执行BeanPostProcessor接口的代码是如下代码:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName); if (result == null) { return result; } } return result; }
其中的getBeanPostProcessors()方法获取的实际就是AbstractBeanFactory的this.beanPostProcessors属性值,看来是这个属性值为空,所以执行的时候没有调用
那接下来要分析的原因就是为什么this.beanPostProcessors属性值为空呢?或者说bean的载入时为什么没有载入进来呢?那就要看它是在哪里载入的了,最终定位到载入是在
AbstractApplicationContext中执行的
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); //这是在子类中启动refreshBeanFactory的地方 // 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. // 设置BeanFactory的后置处理 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 调用BeanFactory的后处理器,这些后处理器是在Bean定义中向容器注册的 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 注册Bean的后处理器,在Bean创建过程中调用 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // 对上下文中的消息源进行初始化 initMessageSource(); // Initialize event multicaster for this context. // 初始化上下文中的事件机制 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 初始化其他的特殊Bean onRefresh(); // Check for listener beans and register them. // 检查监听Bean,并且将这些Bean向容器注册 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.这里是对lazy-init属性进行处理的地方 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // 发布容器事件,结束Refresh过程 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. // 为防止Bean资环占用,在异常处理中,销毁已经在前面过程中生成的单件Bean destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
registerBeanPostProcessors(beanFactory)是载入Bean实现的BeanPostProcessor接口,具体载入代码如下:
public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // Register BeanPostProcessorChecker that logs an info message when // a bean is created during BeanPostProcessor instantiation, i.e. when // a bean is not eligible for getting processed by all BeanPostProcessors. int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // Separate between BeanPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, register the BeanPostProcessors that implement PriorityOrdered. sortPostProcessors(beanFactory, priorityOrderedPostProcessors); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement Ordered. List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } sortPostProcessors(beanFactory, orderedPostProcessors); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // Now, register all regular BeanPostProcessors. List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // Finally, re-register all internal BeanPostProcessors. sortPostProcessors(beanFactory, internalPostProcessors); registerBeanPostProcessors(beanFactory, internalPostProcessors); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
invokeBeanFactoryPostProcessors(beanFactory)是载入Bean实现的BeanFactoryPostProcessor接口,具体载入如下:
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>(); List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryPostProcessor.postProcessBeanDefinitionRegistry(registry); registryPostProcessors.add(registryPostProcessor); } else { regularPostProcessors.add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(beanFactory, priorityOrderedPostProcessors); registryPostProcessors.addAll(priorityOrderedPostProcessors); invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(beanFactory, orderedPostProcessors); registryPostProcessors.addAll(orderedPostProcessors); invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class); registryPostProcessors.add(pp); processedBeans.add(ppName); pp.postProcessBeanDefinitionRegistry(registry); reiterate = true; } } } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(beanFactory, priorityOrderedPostProcessors); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(beanFactory, orderedPostProcessors); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... beanFactory.clearMetadataCache(); }
所以我们可以看到BeanPostProcessor接口和BeanFactoryPostProcessor接口的载入只在abstractApplicationContext中执行了,而在DefaultListableBeanFactory
中没有执行,而我们测试用的工厂就是DefaultListableBeanFactory,所以实际是根本没有载入上面两个接口。
接下来我把测试代码换成如下:
@Test public void test3() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); StudentService studentService = (StudentService)applicationContext.getBean("studentService"); studentService.read(); }
然后执行,可以很清楚的看到那两个接口的方法都执行了。
原因是:ClassPathXmlApplicationContext是abstractApplicationContext的实现,所以使用这个工厂来管理bean,会载入如上两个接口。
总结:
其实我们两个测试代码分别使用了DefaultListableBeanFactory和ClassPathXmlApplicationContext作为Bean工厂,ClassPathXmlApplicationContext底层其实
也是使用的DefaultListableBeanFactory作为Bean工厂,但是ClassPathXmlApplicationContext在DefaultListableBeanFactory的基础上额外载入了
BeanPostProcessor接口和BeanFactoryPostProcessor接口,这个载入是在其父接口AbstractApplicationContext中执行的,这就是为什么test2测试代码不执行这两个接口的方法的原因。
此外,对于两个工厂而言,真正的在初始化的过程中调用这些接口的地方都是在底层工厂DefaultListableBeanFactory中,而DefaultListableBeanFactory
实际是调用的父接口AbstractAutowireCapableBeanFactory的initializeBean方法来进行初始化,从而调用那些初始化接口的方法