我曾在<<spring 一览众山小>>一文中介绍了Spring是一个面向Bean的框架,整个框架的设计是基于Bean的,它的核心就是Bean。Bean其实就是一个Java对象,这个Java对象可能是非常简单的POJO,也可能这个对象会参与到Spring容器生命周期(实现了Spring指定的接口)。Spring 做为Bean的容器提供了Bean的定义、Bean初始化、Bean的组装等功能。本篇文章主要介绍Spring是如何完成Bean的初始化和组装的。
实际编程过程中我们通过Autowired就能实现自动依赖注入等,我们只需在我们的类或者方法上加上特定的注解就可以实现某些功能。这么神奇的事情Spring是如何帮我们做到的呢?本篇文章将为你揭开这神秘的面纱。
Bean的组装
说到Bean的初始化和组装就不得不提BeanPostProcessor,BeanPostProcessor 主要提供了对Bean的组装功能。Spring 提供了许多默认的BeanPostProcessor接口实现从而赋予了Spring依赖注入、事务、缓存等丰富强大的功能。我们也可以通过实现自己的BeanPostProcessor来丰富和完善特殊的功能。
BeanPostProcessor细分出来几个核心的子接口:
- MergedBeanDefinitionPostProcessor 处理Bean的定义
- InstantiationAwareBeanPostProcessor 初始化可以织入的Bean
- DestructionAwareBeanPostProcessor 销毁Bean
InstantiationAwareBeanPostProcessor 和 DestructionAwareBeanPostProcessor在此文章中不做讲解,将在其他篇幅详细说明。
源码MergedBeanDefinitionPostProcessor:
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
/**
* Post-process the given merged bean definition for the specified bean.
* @param beanDefinition the merged bean definition for the bean
* @param beanType the actual type of the managed bean instance
* @param beanName the name of the bean
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}
源码BeanPostProcessor:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
源码 AbstractAutowireCapableBeanFactory
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
....
}
try {
// 调用 InstantiationAwareBeanPostProcessor
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
....
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
....
return beanInstance;
}
// 创建一个Bean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
...
Object exposedObject = bean;
try {
// 实例化、设置对象属性
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 调用MergedBeanDefinitionPostProcessor
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
...
// 初始化Bean
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()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用初始化方法,afterPropertiesSetf方法或init-method方法
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;
}
}
注:BeanPostProcessor的调用是在populateBean方法之后,populateBean方法用来实例化Bean和设置Bean的property。
BeanPostProcessor 接口主要定义了两个方法,postProcessBeforeInitialization方法在Bean初始化(afterPropertiesSetf方法或init-method方法)之前被调用。postProcessAfterInitialization方法在Bean初始化之后被调用。
BeanPostProcessor是多么的重要
源码AbstractApplicationContext
// 容器初始化或刷新时调用
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);
// BeanPostProcessor的注册
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) {
...
}finally {
...
}
}
}
注:BeanPostProcessor也是由Spring来管理的一种Bean,registerBeanPostProcessors方法在注册BeanPostProcessor时是通过beanFactory.getBeanNamesForType(…)方法或取BeanPostProcessor 的Bean 名称。getBeanNamesForType在获取Bean时如果Bean还没有被初始化则对Bean进行初始化,我们知道在Bean初始化时已注册的BeanPostProcessor会被调用。此时会出现BeanPostProcessor注册顺序的问题,如果一个BeanPostProcessor Bean在初始化之后,还未被注册的BeanPostProcessor是无法参与到这个Bean的初始化过程的。此时我们可以通过PriorityOrdered或Ordered接口来控制注册的顺序。
BeanPostProcessor的注册顺序
接下来我们梳理一下BeanPostProcessor的注册顺序,我们可以通过PriorityOrdered或Ordered接口来控制注册的顺序,那么没有实现PriorityOrdered或Ordered接口和实现了PriorityOrdered或Ordered接口的BeanPostProcessor顺序有时怎样的呢?
源码PostProcessorRegistrationDelegate:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForTyp(BeanPostProcessor.class, true, false);
...
// 1、注册实现了PriorityOrdered接口的
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 2、注册实现了PriorityOrdered接口的
sortPostProcessors(beanFactory, orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = newArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 3、注册其他的
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 4、注册实现了MergedBeanDefinitionPostProcessor接口的
sortPostProcessors(beanFactory, internalPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetecto(applicationContext));
}
BeanPostProcessor的注册顺序:
- 实现了PriorityOrdered接口,默认从小到大排
- 实现了Orderedj接口,默认从小到大排
- 其他但没有实现MergedBeanDefinitionPostProcessor,按照获取到顺序
- 实现了MergedBeanDefinitionPostProcessor接口,按照获取到顺序
到此我们已经了解BeanPostProcessor的作用和重要性了,接下来我们看一下Spring是如何通过BeanPostProcessor来实现Autowired注解的
Autowired原理
Autowired注解的支持是由AutowiredAnnotationBeanPostProcessor类实现的。
源码AutowiredAnnotationBeanPostProcessor:
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter{
....
}
AutowiredAnnotationBeanPostProcessor 实现了MergedBeanDefinitionPostProcessor接口,在检查到存在Autowired注解或Inject注解时,会修改Bean的定义。在之后Bean初始化时就自动注入了。