IOC容器中那些鲜为人知的事儿
通过前面章节中对SpringIOC容器的源码分析,我们已经基本上了解了Spring IOC容器对Bean定义资源的定位、读入和解析过程,同时也清楚了当用户通过getBean方法向IOC容器获取被管理的Bean时,IOC容器对Bean进行的初始化和依赖注入过程,这些是Spring IOC容器的基本功能特性.
SpringIOC容器还有一些高级特性,如使用lazy-init属性对Bean预初始化、FactoryBean产生或者修饰Bean对象的生成、IOC容器初始化Bean过程中使用BeanPostProcessor后置处理器对Bean声明周期事件管理和IOC容器的autowiring自动装配功能等.
1.SpringIOC容器的lazy-init属性实现预实例化
通过前面我们对IOC容器的实现和工作原理分析,我们知道IOC容器的初始化过程就是对Bean定义资源的定位、载入和注册,此时容器对Bean的依赖注入并没有发生,依赖注入主要是在应用程序第一次向容器索取Bean时,通过getBean方法的调用完成.
当Bean定义资源的<Bean>元素中配置了lazy-init属性时,容器将会在初始化的时候对所配置的Bean进行预实例化,Bean的依赖注入在容器初始化的时候就已经完成.这样,当应用程序第一次向容器索取被管理的Bean时,就不用再初始化和对Bean进行依赖注入了,直接从容器中获取已经完成依赖注入的现成Bean,可以提高应用第一次向容器获取Bean的性能.
下面我们通过代码分析容器预实例化的实现过程.
1.1 refresh()
先从IOC容器的初始会过程开始,通过前面文章分析,我们知道IOC容器读入已经定位的Bean定义资源是从refresh方法开始的,我们首先从AbstractApplicationContext类的refresh方法入手分析,源码如下:
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
// 加锁,避免 #refresh() 和 #close() 方法,自身或者对方并行执行.
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 准备刷新的上下文, 获取容器的当前时间, 同时给容器设置同步标识
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 初始化 BeanFactory ,并进行 XML 文件读取, Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 对 BeanFactory 配置容器特性, 例如类加载器、时间处理器等
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 子类覆盖该方法,做 BeanFactory 的额外的处理, 为容器的某些子类指定特殊的BeanPost事件处理器
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 激活各种 BeanFactory 处理器,例如 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册拦截 Bean 创建的 BeanPostProcessor.这里只是注册,真正的调用在 #getBean(...) 的时,即 Bean 创建的时候.
// 注意:
// 1. BeanFactoryPostProcessor 作用于 BeanDefinition
// 2. BeanPostProcessor 作用于 Bean
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化信息源, 和国际化相关
initMessageSource();
// Initialize event multicaster for this context.
// 初始化 Application Event Multicaster(容器事件传播器)
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 留给子类,来初始化其他特殊的 Bean 对象们
onRefresh();
// Check for listener beans and register them.
// 注册监听器们
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化非延迟加载的单例
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
destroyBeans()
// Reset 'active' flag.
// 取消refresh操作,重置容器的同步标识
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();
}
}
}
}
在refresh()方法中ConfigurableListableBeanFactorybeanFactory=obtainFreshBeanFactory();启动了Bean定义资源的载入、注册过程,而finishBeanFactoryInitialization方法是对注册后的Bean定义中的预实例化(lazy-init=false,Spring默认就是预实例化,即为true)的Bean进行处理的地方.
1.2 finishBeanFactoryInitialization处理预实例化Bean
当Bean定义资源被载入IOC容器之后,容器将Bean定义资源解析为容器内部的数据结构BeanDefinition注册到容器中,AbstractApplicationContext类中的finishBeanFactoryInitialization方法对配置了预实例化属性的Bean进行预初始化过程,源码如下:
/**
* 对配置了 lazy-init 属性的Bean进行预实例化过程
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 这是Spring3以后新加的代码, 为容器指定一个转换服务(conversionService), 在对某些Bean属性进行转换时使用
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
// 为了类型匹配, 停止使用临时的类加载器
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 冻结 BeanDefinition 配置
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 对配置了lazy-init属性的单态模式Bean进行预实例化处理
beanFactory.preInstantiateSingletons();
}
ConfigurableListableBeanFactory是一个接口,其preInstantiateSingletons方法由其子类DefaultListableBeanFactory提供.
1.3 DefaultListableBeanFactory对配置lazy-init属性单态Bean的预实例化
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// 获得所有 Bean 名字的集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 遍历 Bean 名字的集合,触发 Bean 加载
for (String beanName : beanNames) {
// 获得 RootBeanDefinition 对象
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 单例 && 非延迟加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果是 FactoryBean
if (isFactoryBean(beanName)) {
// 获得 FactoryBean 自身这个 Bean
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
// 判断是否要提前初始化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
} else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
// 如果要,加载 FactoryBean 要创建的 Bean 对象
if (isEagerInit) {
getBean(beanName);
}
}
} else {
// 如果非 FactoryBean ,直接加载 Bean 对象
getBean(beanName);
}
}
}
// 遍历所有单例 Bean ,触发后置初始化方法,即 SmartInitializingSingleton 对象,所有非 lazy 单例 Bean 实例化完成后的回调方法.
// Spring 4.1 新增的特性
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) { // 安全模式
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
}
通过对lazy-init处理源码的分析,我们可以看出,如果设置了lazy-init属性,则容器在完成Bean定义的注册之后,会通过getBean方法,触发对指定Bean的初始化和依赖注入过程,这样当应用第一次向容器索取所需的Bean时,容器不再需要对Bean进行初始化和依赖注入,直接从已经完成实例化和依赖注入的Bean中取一个现成的Bean,这样就提高了第一次获取Bean的性能.
3.FactoryBean的实现
在Spring中,有两个很容易混淆的类: BeanFactory和FactoryBean.
BeanFactory: Bean工厂,是一个工厂(Factory),我们Spring IOC容器的最顶层接口就是这个BeanFactory,它的作用是管理Bean,即实例化、定位、配置应用程序中的对象及建立这些对象间的依赖.FactoryBean: 工厂Bean,是一个Bean,作用是产生其他bean实例.通常情况下,这种bean没有什么特别的要求,仅需要提供一个工厂方法,该方法用来返回其他bean实例.通常情况下,bean无须自己实现工厂模式,Spring容器担任工厂角色;但少数情况下,容器中的bean本身就是工厂,其作用是产生其它bean实例.
当用户使用容器本身时,可以使用转义字符"&"来得到FactoryBean本身,以区别通过FactoryBean产生的实例对象和FactoryBean对象本身.在BeanFactory中通过如下代码定义了该转义字符:
StringFACTORY_BEAN_PREFIX="&";
如果myJndiObject是一个FactoryBean,则使用&myJndiObject得到的是myJndiObject对象,而不是myJndiObject产生出来的对象.
3.1 FactoryBean的源码如下
/**
* From 《Spring 源码深度解析》P83 页
*
* 一般情况下,Spring 通过反射机制利用 bean 的 class 属性指定实现类来实例化 bean .
* 某些情况下,实例化 bean 过程比较复杂,如果按照传统的方式,则需要在 <bean> 中提供大量的配置信息,
* 配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案.Spring 为此提供了一个 FactoryBean 的工厂类接口,
* 用户可以通过实现该接口定制实例化 bean 的逻辑.
*
* FactoryBean 接口对于 Spring 框架来说占有重要的地址,Spring 自身就提供了 70 多个 FactoryBean 的实现
* 它们隐藏了实例化一些复杂 bean 的细节,给上层应用带来了便利.
*/
public interface FactoryBean<T> {
/**
* 获取容器管理的实例对象
*/
@Nullable
T getObject() throws Exception;
/**
* 获取Bean工厂创建的对象的类型
*/
@Nullable
Class<?> getObjectType();
/**
* Bean工厂创建的对象是否是单态模式, 如果是单台模式, 则整个容器中只有一个实例对象, 每次请求都返回同一个实例对象
*/
default boolean isSingleton() {
return true;
}
}
3.2 AbstractBeanFactory的getBean方法调用FactoryBean
在前面我们分析Spring IOC容器实例化Bean并进行依赖注入过程的源码时,提到在getBean方法触发容器实例化Bean的时候会调用AbstractBeanFactory的doGetBean方法来进行实例化的过程,源码如下:
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 根据指定的名称获取被管理Bean名称,剥离指定名称中对容器的相关依赖
// 如果指定的是别名, 将别名转换为规范的Bean名称
final String beanName = transformedBeanName(name);
Object bean;
// 从缓存中或者实例工厂中获取 Bean 对象
// 对于单例模式的Bean, 整个IOC容器中只创建一个, 不需要重复创建
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
// 指定名称的Bean在容器中已有单例模式的Bean被创建, 直接返回已经创建的Bean
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
// 注意: BeanFactory是管理容器中Bean的工程,FactoryBean是创建创建对象的工厂Bean, 两者之间有区别
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 因为 Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 对IOC容器中是否存在指定名称的BeanDefinition进行检查
// 首先加查是否能在当前的BeanFactory中获取的所需要的Bean, 如果不能则委托当前容器的父级容器去查询
// 如果当前还是找不到则沿着容器的继承体系向父级容器查询
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 当前容器的父级容器存在, 并且当前容器中不存在指定名称的Bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 解析指定Bean名称的原始名称
String nameToLookup = originalBeanName(name);
// 如果,父类容器为 AbstractBeanFactory ,直接递归查找
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
// 用明确的 args 从 parentBeanFactory 中,获取 Bean 对象
} else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
// 用明确的 requiredType 从 parentBeanFactory 中,获取 Bean 对象
} else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
// 直接使用 nameToLookup 从 parentBeanFactory 获取 Bean 对象
} else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 如果不是仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
// 更加指定Bean名称获取其父级的Bean定义, 主要解决Bean继承时子类合并父类公共属性问题
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查给定的合并的 BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 处理所依赖的 bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 若给定的依赖 bean 已经注册为依赖给定的 bean
// 即循环依赖的情况,抛出 BeanCreationException 异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 递归调用getBean方法, 获取当前Bean的依赖Bean
registerDependentBean(dep, beanName);
try {
// 递归处理依赖 Bean
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// bean 实例化
// Create bean instance.
// 创建单例模式Bean的实例对象
if (mbd.isSingleton()) {
// 这里使用了一个匿名内部类, 创建Bean实例对象,并且注册所依赖的对象
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建一个指定Bean实例对象, 如果有父级继承, 则合并子类和父类的定义
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
// 显式从单例缓存中删除 Bean 实例
// 因为单例模式下为了解决循环依赖,可能他已经存在了,所以销毁它. TODO 芋艿
destroySingleton(beanName);
throw ex;
}
});
// 获取给定Bean的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// IOC容器创建原型模式Bean实例对象
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance;
try {
// 回调beforePrototypeCreation方法, 默认的功能是注册当前创建的原型对象
beforePrototypeCreation(beanName);
// 创建指定Bean对象实例
prototypeInstance = createBean(beanName, mbd, args);
} finally {
// 回调afterPrototypeCreation方法, 默认的功能告诉IOC容器指定Bean的原型对象不再创建
afterPrototypeCreation(beanName);
}
// 获取给定Bean的实例对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 要创建的Bean既不是单例模式, 也不是原型模式, 则根据Bean定义资源中配置的生命周期范围, 选择实例化Bean的合适方法
// 这种在web应用程序中比较常用, 如: request, session, application等生命周期
else {
// 获得 scopeName 对应的 Scope 对象
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
// Bean定义资源中没有配置生命周期范围, 则Bean定义不合法
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 这里又使用了一个匿名内部类, 从指定的 scope 下创建 bean
Object scopedInstance = scope.get(beanName, () -> {
// 加载前置处理
beforePrototypeCreation(beanName);
try {
// 创建 Bean 对象
return createBean(beanName, mbd, args);
} finally {
// 加载后缀处理
afterPrototypeCreation(beanName);
}
});
// 从 Bean 实例中获取对象
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 检查需要的类型是否符合 bean 的实际类型
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 执行转换
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
// 转换失败,抛出 BeanNotOfRequiredTypeException 异常
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
} catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
/**
* 获取给定Bean的实例对象, 主要是完成FactoryBean的相关处理
*/
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 若为工厂类引用(name 以 & 开头)
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
// 如果是 NullBean,则直接返回
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 如果 beanInstance 不是 FactoryBean 类型,则抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// 到这里我们就有了一个 Bean 实例,当然该实例可能是会是是一个正常的 bean 又或者是一个 FactoryBean
// 如果是 FactoryBean,我们则创建该 Bean
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
// 若 BeanDefinition 为 null,则从缓存中加载 Bean 对象
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
// 若 object 依然为空,则可以确认,beanInstance 一定是 FactoryBean .从而,使用 FactoryBean 获得 Bean 对象
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// containsBeanDefinition 检测 beanDefinitionMap 中也就是在所有已经加载的类中
// 检测是否定义 beanName
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
// 将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition,
// 如果指定 BeanName 是子 Bean 的话同时会合并父类的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
// 是否是用户定义的,而不是应用程序本身定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 核心处理方法,使用 FactoryBean 获得 Bean 对象
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
}
在上面获取给定Bean的实例对象的getObjectForBeanInstance方法中,会调用FactoryBeanRegistrySupport类的getObjectFromFactoryBean方法,该方法实现了Bean工厂生产Bean实例对象.
Dereference(解引用): 一个在C/C++中应用比较多的术语,在C++中,"*"是解引用符号,而"&"是引用符号,解引用是指变量指向的是所引用对象的本身数据,而不是引用对象的内存地址.
3.3 AbstractBeanFactory生产Bean实例对象
AbstractBeanFactory类中生产Bean实例对象的主要源码如下:
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 为单例模式且缓存中存在
if (factory.isSingleton() && containsSingleton(beanName)) {
// 单例锁, 多线程同步, 以防止数据不一致
synchronized (getSingletonMutex()) {
// 从缓存中获取指定的 factoryBean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 为空,则从 FactoryBean 中获取对象
object = doGetObjectFromFactoryBean(factory, beanName);
// 从缓存中获取
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
} else {
// 需要后续处理
if (shouldPostProcess) {
// 若该 Bean 处于创建中,则返回非处理对象,而不是存储它
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 单例 Bean 的前置处理
beforeSingletonCreation(beanName);
try {
// 对从 FactoryBean 获取的对象进行后处理
// 生成的对象将暴露给 bean 引用
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
} finally {
// 单例 Bean 的后置处理
afterSingletonCreation(beanName);
}
}
// 添加到 factoryBeanObjectCache 中,进行缓存
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
} else {
// 为空,则从 FactoryBean 中获取对象
Object object = doGetObjectFromFactoryBean(factory, beanName);
// 需要后续处理
if (shouldPostProcess) {
try {
// 对从 FactoryBean 获取的对象进行后处理
// 生成的对象将暴露给 bean 引用
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
/**
* 调用Beang工厂的getObject方法生成指定Bean的实例对象
*/
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
// 需要权限验证
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
// 实现PrivilegedExceptionAction接口的匿名内部类,根据JVM权限检查, 然后决定BeanFactory创建实例对象
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
// 调用FactoryBean接口实现类的创建对象方法
object = factory.getObject();
}
} catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
// 创建出来的实例对象为null, 或者因为单态对象正在创建而返回null
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
}
从上面的源码分析中,我们可以看出,BeanFactory接口调用其实现类的getObject方法来实现创建Bean实例对象的功能.
3.4 工厂Bean的实现类getObject方法创建Bean实例对象
FactoryBean的实现类有非常多,比如: Proxy、RMI、JNDI、ServletContextFactoryBean等等,FactoryBean接口为Spring容器提供了一个很好的封装机制,具体的getObject有不同的实现类根据不同的实现策略来具体提供,我们分析一个最简单的AnnotationTestFactoryBean的实现源码:
public class AnnotationTestBeanFactory implements FactoryBean<FactoryCreatedAnnotationTestBean> {
private final FactoryCreatedAnnotationTestBean instance = new FactoryCreatedAnnotationTestBean();
public AnnotationTestBeanFactory() {
this.instance.setName("FACTORY");
}
/**
* AnnotationTestBeanFactory产生Bean实例对象的实现
*/
@Override
public FactoryCreatedAnnotationTestBean getObject() throws Exception {
return this.instance;
}
@Override
public Class<? extends IJmxTestBean> getObjectType() {
return FactoryCreatedAnnotationTestBean.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
其他的Proxy,RMI,JNDI等等,都是根据相应的策略提供getObject的实现.这里不做一一分析,这已经不是Spring的核心功能,有需要的时候再去深入研究.
4.BeanPostProcessor后置处理器的实现
BeanPostProcessor后置处理器是Spring IOC容器经常使用到的一个特性,这个Bean后置处理器是一个监听器,可以监听容器触发的Bean声明周期事件.后置处理器向容器注册以后,容器中管理的Bean就具备了接收IOC容器事件回调的能力.
BeanPostProcessor的使用非常简单,只需要提供一个实现接口BeanPostProcessor的实现类,然后在Bean的配置文件中设置即可.
4.1 BeanPostProcessor的源码如下
public interface BeanPostProcessor {
/**
* 为在Bean的初始化之前提供回调入口
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* 为在Bean的初始化之后提供回调入口
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
这两个回调的入口都是和容器管理的Bean的生命周期事件紧密相关,可以为用户提供在SpringIOC容器初始化Bean过程中自定义的处理操作.
4.2 AbstractAutowireCapableBeanFactory类对容器生成的Bean添加后置处理器
BeanPostProcessor后置处理器的调用发生在Spring IOC容器完成对Bean实例对象的创建和属性的依赖注入完成之后,在对Spring依赖注入的源码分析过程中我们知道,当应用程序第一次调用getBean方法(lazy-init预实例化除外)向Spring IOC容器索取指定Bean时触发Spring IOC容器创建Bean实例对象并进行依赖注入的过程,其中真正实现创建Bean对象并进行依赖注入的方法是AbstractAutowireCapableBeanFactory类的doCreateBean方法,主要源码如下:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/**
* 真正创建 Bean 的方法
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
...
// Initialize the bean instance.
// 开始初始化 bean 实例对象
Object exposedObject = bean;
try {
// 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性,则会递归初始依赖 bean
populateBean(beanName, mbd, instanceWrapper);
// 在对Bean实例化对象生成和依赖注入完成之后, 开始对Bean实例对象进行初始化, 为Bean实例对象应用BeanPostProcessor后置处理器
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);
}
}
...
// 为应用返回所需要的实例对象
return exposedObject;
}
}
从上面的代码中我们知道,为Bean实例对象添加BeanPostProcessor后置处理器的入口的是initializeBean方法.
4.3 initializeBean方法为容器产生的Bean实例对象添加BeanPostProcessor后置处理器
同样在AbstractAutowireCapableBeanFactory类中,initializeBean方法实现为容器创建的Bean实例对象添加BeanPostProcessor后置处理器,源码如下:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/**
*初始容器创建的Bean实例对象, 为其添加BeanPostProcessor后置处理器
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// JDK的安全机制验证权限
if (System.getSecurityManager() != null) {
// 实现PrivilegedAction接口的匿名内部类
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
// 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
// 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
// 后处理器,before
Object wrappedBean = bean;
// 对BeanPostProcessor后置处理器的postProcessBeforeInitialization回调方法的调用,为Bean实例初始化前做一些处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置文件中通过init-Method属性指定的
try {
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 后处理器,after
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
/**
* 调用BeanPostProcessors后置处理器实例对象初始化之前的处理方法
*/
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 遍历 BeanPostProcessor 数组
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 调用Bean实例所有的后置处理中的初始化前处理方法, 为Bean实例对象在初始化之前做一些自定义的处理操作
Object current = processor.postProcessBeforeInitialization(result, beanName);
// 返回空,则返回 result
if (current == null) {
return result;
}
// 修改 result
result = current;
}
return result;
}
/**
* 调用BeanPostProcessors后置处理器实例对象初始化之后的处理方法
*/
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
// 遍历 BeanPostProcessor
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 调用Bean实例所有的后置处理中的初始化前处理方法, 为Bean实例对象在初始化之后做一些自定义的处理操作
Object current = processor.postProcessAfterInitialization(result, beanName);
// 返回空,则返回 result
if (current == null) {
return result;
}
// 修改 result
result = current;
}
return result;
}
}
BeanPostProcessor是一个接口,其初始化前的操作方法和初始化后的操作方法均委托其实现子类来实现,在Spring中,BeanPostProcessor的实现子类非常的多,分别完成不同的操作,如: AOP面向切面编程的注册通知适配器、Bean对象的数据校验、Bean继承属性/方法的合并等等,我们以最简单的AOP切面织入来简单了解其主要的功能.
4.4 AdvisorAdapterRegistrationManager在Bean对象初始化后注册通知适配器
AdvisorAdapterRegistrationManager是BeanPostProcessor的一个实现类,其主要的作用为容器中管理的Bean注册一个面向切面编程的通知适配器,以便在Spring容器为所管理的Bean进行面向切面编程时提供方便,其源码如下:
public class AdvisorAdapterRegistrationManager implements BeanPostProcessor {
/**
* 容器中负责管理切面通知适配器注册的对象
*/
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
this.advisorAdapterRegistry = advisorAdapterRegistry;
}
/**
* BeanPostProcessor在Bean对象初始化前的操作
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// //没有做任何操作,直接返回容器创建的Bean对象
return bean;
}
/**
* BeanPostProcessor在Bean对象初始化后的操作
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AdvisorAdapter){
// 如果容器创建的Bean实例对象是一个切面通知适配器,则向容器的注册
this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);
}
return bean;
}
}
其他的BeanPostProcessor接口实现类的也类似,都是对Bean对象使用到的一些特性进行处理,或者向IOC容器中注册,为创建的Bean实例对象做一些自定义的功能增加,这些操作是容器初始化Bean时自动触发的,不需要人为干预.
5 SpringIOC容器autowiring实现原理
Spring IOC容器提供了两种管理Bean依赖关系的方式:
- 显式管理: 通过
BeanDefinition的属性值和构造方法实现Bean依赖关系管理. - autowiring:
Spring IOC容器的依赖自动装配功能,不需要对Bean属性的依赖关系做显式的声明,只需要在配置好autowiring属性,IOC容器会自动使用反射查找属性的类型和名称,然后基于属性的类型或者名称来自动匹配容器中管理的Bean,从而自动地完成依赖注入.
通过对autowiring自动装配特性的理解,我们知道容器对Bean的自动装配发生在容器对Bean依赖注入的过程中.
在前面对Spring IOC容器的依赖注入过程源码分析中,我们已经知道了容器对Bean实例对象的属性注入的处理发生在AbstractAutoWireCapableBeanFactory类中的populateBean方法中,我们通过程序流程分析autowiring的实现原理:
5.1 AbstractAutoWireCapableBeanFactory对Bean实例进行属性依赖注入
应用第一次通过getBean方法(配置了lazy-init预实例化属性的除外)向IOC容器索取Bean时,容器创建Bean实例对象,并且对Bean实例对象进行属性依赖注入,AbstractAutoWireCapableBeanFactory的populateBean方法就是实现Bean属性依赖注入的功能,其主要源码如下:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/**
* 将 Bean 属性设置到生成的实例对象上
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance
*/
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 没有实例化对象
if (bw == null) {
// 有属性,则抛出 BeanCreationException 异常
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
// 没有属性,直接 return 返回
} else {
// Skip property population phase for null instance.
return;
}
}
// 在设置属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true;
// bean 不是"合成"的,即未由应用程序本身定义
if (!mbd.isSynthetic()
// 是否持有 InstantiationAwareBeanPostProcessor
&& hasInstantiationAwareBeanPostProcessors()) {
// 迭代所有的 BeanPostProcessors
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 如果为 InstantiationAwareBeanPostProcessor
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 返回值为是否继续填充 bean
// postProcessAfterInstantiation:如果应该在 bean上面设置属性则返回 true,否则返回 false
// 一般情况下,应该是返回true.
// 返回 false 的话,将会阻止在此 Bean 实例上调用任何后续的 InstantiationAwareBeanPostProcessor 实例.
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 如果后续处理器发出停止填充命令,则终止后续操作
if (!continueWithPropertyPopulation) {
return;
}
// 获取容器在解析 bean 定义资源时为 BeanDefinition 中设置的属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 自动注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
// 将 PropertyValues 封装成 MutablePropertyValues 对象
// MutablePropertyValues 允许对属性进行简单的操作,并提供构造函数以支持Map的深度复制和构造.
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 根据名称自动注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 根据类型自动注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 对非autowiring的属性进行依赖注入处理
...
}
}
5.2 SpringIOC容器根据Bean名称或者类型进行autowiring自动依赖注入
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
/**
* 根据类型对属性进行自动依赖注入
*/
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取 TypeConverter 实例
// 使用自定义的 TypeConverter,用于取代默认的 PropertyEditor 机制
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
// 存放解析的要注入的属性
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 获取非简单属性(不是简单继承的属性,如原始类型,字符URL 等都是简单属性)进行处理
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 遍历 propertyName 数组
for (String propertyName : propertyNames) {
try {
// 获取指定属性名称的 PropertyDescriptor(属性描述求) 实例
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
// 不对Object类型的属性进行autowiring自动依赖注入
if (Object.class != pd.getPropertyType()) {
// 探测指定属性的 set 方法
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
// 检查指定类型是否可以被转换为目标对象的类型
boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
// 创建一个要被注入的依赖描述
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 解析指定 beanName 的属性所匹配的值,并把解析到的属性名称存储在 autowiredBeanNames 中
// 当属性存在多个封装 bean 时将会找到所有匹配的 bean 并将其注入
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
// 为属性复制所引用的对象
pvs.add(propertyName, autowiredArgument);
}
// 遍历 autowiredBeanName 数组
for (String autowiredBeanName : autowiredBeanNames) {
// 指定名称属性注册依赖Bean名称, 进行属性依赖注入
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
// 清空 autowiredBeanName 数组
autowiredBeanNames.clear();
}
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
}
通过上面的源码分析,我们可以看出来通过属性名进行自动依赖注入的相对比通过属性类型进行自动依赖注入要稍微简单一些,但是真正实现属性注入的是DefaultSingletonBeanRegistry类的registerDependentBean方法.
5.3 DefaultSingletonBeanRegistry的registerDependentBean方法对属性注入
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/**
* 为指定的Bean注入依赖的Bean
*/
public void registerDependentBean(String beanName, String dependentBeanName) {
// 获取 beanName, 将别名转换为规范的Bean名称
String canonicalName = canonicalName(beanName);
// 添加 <canonicalName, <dependentBeanName>> 到 dependentBeanMap 中
// 多线程同步, 保证容器内数据的一致性
// 先从容器中: bean名称 --> 全部依赖Bean名称集合查找给定名称Bean的依赖Bean
synchronized (this.dependentBeanMap) {
// 获取给定名称Bean的所有依赖Bean名称
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
// 添加 <dependentBeanName, <canonicalName>> 到 dependenciesForBeanMap 中
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
}
通过对autowiring的源码分析,我们可以看出,autowiring的实现过程:
- 对Bean的属性代调用
getBean方法,完成依赖Bean的初始化和依赖注入 - 将依赖Bean的属性引用设置到被依赖的Bean属性上
- 将依赖Bean的名称和被依赖Bean的名称存储在IOC容器的集合中
Spring IOC容器的autowiring属性自动依赖注入是一个很方便的特性,可以简化开发时的配置.
但是凡是都有两面性,自动属性依赖注入也有不足,首先,Bean的依赖关系在配置文件中无法很清楚地看出来,对于维护造成一定困难.其次,由于自动依赖注入是Spring容器自动执行的,容器是不会智能判断的,如果配置不当,将会带来无法预料的后果,所以自动依赖注入特性在使用时还是综合考虑.