通过前面章节中对Spring IOC 容器的源码分析,我们已经基本上了解了Spring IOC 容器对Bean 定义资源的定位、载入和注册过程,同时也清楚了当用户通过getBean()方法向IOC 容器获取被管理的Bean时,IOC 容器对Bean 进行的初始化和依赖注入过程,这些是Spring IOC 容器的基本功能特性。Spring IOC 容器还有一些高级特性,如使用lazy-init 属性对Bean 预初始化、FactoryBean 产生或者修饰Bean 对象的生成、IOC 容器初始化Bean 过程中使用BeanPostProcessor 后置处理器对Bean 声明周期事件管理等。
关于延时加载
通过前面我们对IOC 容器的实现和工作原理分析,我们已经知道IOC 容器的初始化过程就是对Bean定义资源的定位、载入和注册,此时容器对Bean 的依赖注入并没有发生,依赖注入主要是在应用程序第一次向容器索取Bean 时,通过getBean()方法的调用完成。
当Bean 定义资源的<Bean>元素中配置了lazy-init=false 属性时,容器将会在初始化的时候对所配置的Bean 进行预实例化,Bean 的依赖注入在容器初始化的时候就已经完成。这样,当应用程序第一次向容器索取被管理的Bean 时,就不用再初始化和对Bean 进行依赖注入了,直接从容器中获取已经完成依赖注入的现成Bean,可以提高应用第一次向容器获取Bean 的性能。
1、refresh()方法
先从IOC 容器的初始化过程开始,我们知道IOC 容器读入已经定位的Bean 定义资源是从refresh()方法开始的,我们首先从AbstractApplicationContext 类的refresh()方法入手分析,源码如下:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
prepareRefresh();
//告诉子类启动refreshBeanFactory()方法,Bean 定义资源文件的载入从
//子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//为BeanFactory 配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
//为容器的某些子类指定特殊的BeanPost 事件处理器
postProcessBeanFactory(beanFactory);
//调用所有注册的BeanFactoryPostProcessor 的Bean
invokeBeanFactoryPostProcessors(beanFactory);
//为BeanFactory 注册BeanPost 事件处理器.
//BeanPostProcessor 是Bean 后置处理器,用于监听容器触发的事件
registerBeanPostProcessors(beanFactory);
//初始化信息源,和国际化相关.
initMessageSource();
//初始化容器事件传播器.
initApplicationEventMulticaster();
//调用子类的某些特殊Bean 初始化方法
onRefresh();
//为事件传播器注册事件监听器.
registerListeners();
//初始化所有剩余的单例Bean
finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
//销毁已创建的Bean
destroyBeans();
//取消refresh 操作,重置容器的同步标识.
cancelRefresh(ex);
throw ex;
} finally {
resetCommonCaches();
}
}
}
在refresh()方法中ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory();启动了Bean 定义资源的载入、注册过程,而finishBeanFactoryInitialization 方法是对注册后的Bean定义中的预实例化(lazy-init=false,Spring 默认就是预实例化,即为true)的Bean 进行处理的地方。
2、finishBeanFactoryInitialization 处理预实例化Bean
当Bean 定义资源被载入IOC 容器之后, 容器将Bean 定义资源解析为容器内部的数据结构BeanDefinition 注册到容器中,AbstractApplicationContext 类中的finishBeanFactoryInitialization()方法对配置了预实例化属性的Bean 进行预初始化过程,源码如下:
//对配置了lazy-init 属性的Bean 进行预实例化处理
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//这是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));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
//为了类型匹配,停止使用临时的类加载器
beanFactory.setTempClassLoader(null);
//缓存容器中所有注册的BeanDefinition 元数据,以防被修改
beanFactory.freezeConfiguration();
//对配置了lazy-init 属性的单态模式Bean 进行预实例化处理
beanFactory.preInstantiateSingletons();
}
ConfigurableListableBeanFactory 是一个接口, 其preInstantiateSingletons() 方法由其子类DefaultListableBeanFactory 提供。
3、DefaultListableBeanFactory 对配置lazy-init 属性单态Bean 的预实例化
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
//获取指定名称的Bean 定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//Bean 不是抽象的,是单态模式的,且lazy-init 属性配置为false
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//如果指定名称的bean 是创建容器的Bean
if (isFactoryBean(beanName)) {
//FACTORY_BEAN_PREFIX=”&”,当Bean 名称前面加”&”符号时,获取的是产生容器对象本身,而不是容器产生的Bean.
//调用getBean 方法,触发容器对Bean 实例化和依赖注入过程
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
//标识是否需要预实例化
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());
}
if (isEagerInit) {
//调用getBean 方法,触发容器对Bean 实例化和依赖注入过程
getBean(beanName);
}
} else {
getBean(beanName);
}
}
}
}
通过对lazy-init 处理源码的分析,我们可以看出,如果设置了lazy-init 属性,则容器在完成Bean 定义的注册之后,会通过getBean 方法,触发对指定Bean 的初始化和依赖注入过程,这样当应用第一次向容器索取所需的Bean 时,容器不再需要对Bean 进行初始化和依赖注入,直接从已经完成实例化和依赖注入的Bean 中取一个现成的Bean,这样就提高了第一次获取Bean 的性能。
关于FactoryBean 和BeanFactory
在Spring 中,有两个很容易混淆的类:BeanFactory 和FactoryBean。
BeanFactory:Bean 工厂,是一个工厂(Factory),我们Spring IOC 容器的最顶层接口就是这个BeanFactory,它的作用是管理Bean,即实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
FactoryBean:工厂Bean,是一个Bean,作用是产生其他bean 实例。通常情况下,这种Bean 没有什么特别的要求,仅需要提供一个工厂方法,该方法用来返回其他Bean 实例。通常情况下,Bean 无须自己实现工厂模式,Spring 容器担任工厂角色;但少数情况下,容器中的Bean 本身就是工厂,其作用是产生其它Bean 实例。
当用户使用容器本身时,可以使用转义字符”&”来得到FactoryBean 本身,以区别通过FactoryBean产生的实例对象和FactoryBean 对象本身。在BeanFactory 中通过如下代码定义了该转义字符:
String FACTORY_BEAN_PREFIX = "&";
如果myJndiObject 是一个FactoryBean,则使用&myJndiObject 得到的是myJndiObject 对象,而不是myJndiObject 产生出来的对象。
1、FactoryBean 源码
//工厂Bean,用于产生其他对象
public interface FactoryBean<T> {
//获取容器管理的对象实例
@Nullable
T getObject() throws Exception;
//获取Bean 工厂创建的对象的类型
@Nullable
Class<?> getObjectType();
//Bean 工厂创建的对象是否是单态模式,如果是单态模式,则整个容器中只有一个实例
//对象,每次请求都返回同一个实例对象
default boolean isSingleton() {
return true;
}
}
2、AbstractBeanFactory 的getBean()方法调用FactoryBean
在前面我们分析Spring IOC 容器实例化Bean 并进行依赖注入过程的源码时,提到在getBean()方法触发容器实例化Bean 的时候会调用AbstractBeanFactory 的doGetBean()方法来进行实例化的过程,源码如下:
//真正实现向IOC 容器获取Bean 的功能,也是触发依赖注入功能的地方
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;
// Eagerly check singleton cache for manually registered singletons.
//先从缓存中取是否已经有被创建过的单态类型的Bean
//对于单例模式的Bean 整个IOC 容器中只创建一次,不需要重复创建
Object sharedInstance = getSingleton(beanName);
//IOC 容器创建单例模式Bean 实例对象
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
//如果指定名称的Bean 在容器中已有单例模式的Bean 被创建
//直接返回已经创建的Bean
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//获取给定Bean 的实例对象,主要是完成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.
//缓存没有正在创建的单例模式Bean
//缓存中已经有已经创建的原型模式Bean
//但是由于循环引用的问题导致实例化对象失败
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//对IOC 容器中是否存在指定名称的BeanDefinition 进行检查,首先检查是否
//能在当前的BeanFactory 中获取的所需要的Bean,如果不能则委托当前容器
//的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找
BeanFactory parentBeanFactory = getParentBeanFactory();
//当前容器的父级容器存在,且当前容器中不存在指定名称的Bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
//解析指定Bean 名称的原始名称
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
//委派父级容器根据指定名称和显式的参数查找
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else {
// No args -> delegate to standard getBean Method.
//委派父级容器根据指定名称和类型查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//创建的Bean 是否需要进行类型验证,一般不需要
if (!typeCheckOnly) {
//向容器标记指定的Bean 已经被创建
markBeanAsCreated(beanName);
}
try {
//根据指定Bean 名称获取其父级的Bean 定义
//主要解决Bean 继承时子类合并父类公共属性问题
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//获取当前Bean 所有依赖Bean 的名称
String[] dependsOn = mbd.getDependsOn();
//如果当前Bean 有依赖Bean
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//递归调用getBean 方法,获取当前Bean 的依赖Bean
registerDependentBean(dep, beanName);
//把被依赖Bean 注册给当前依赖的Bean
getBean(dep);
}
}
// 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 缓存中清除实例对象
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.
//原型模式(Prototype)是每次都会创建一个新的对象
Object prototypeInstance = null;
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 {
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 {
//这里又使用了一个匿名内部类,获取一个指定生命周期范围的实例
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
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;
}
}
...
return (T) bean;
}
//获取给定Bean 的实例对象,主要是完成FactoryBean 的相关处理
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//容器已经得到了Bean 实例对象,这个实例对象可能是一个普通的Bean,
//也可能是一个工厂Bean,如果是一个工厂Bean,则使用它创建一个Bean 实例对象,
//如果调用本身就想获得一个容器的引用,则指定返回这个工厂Bean 实例对象
//如果指定的名称是容器的解引用(dereference,即是对象本身而非内存地址),
//且Bean 实例也不是创建Bean 实例对象的工厂Bean
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
//如果Bean 实例不是工厂Bean,或者指定名称是容器的解引用,
//调用者向获取对容器的引用,则直接返回当前的Bean 实例
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//处理指定名称不是容器的解引用,或者根据名称获取的Bean 实例对象是一个工厂Bean
//使用工厂Bean 创建一个Bean 的实例对象
Object object = null;
if (mbd == null) {
//从Bean 工厂缓存中获取给定名称的Bean 实例对象
object = getCachedObjectForFactoryBean(beanName);
}
//让Bean 工厂生产给定名称的Bean 对象实例
if (object == null) {
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
//如果从Bean 工厂生产的Bean 是单态模式的,则缓存
if (mbd == null && containsBeanDefinition(beanName)) {
//从容器中获取指定名称的Bean 定义,如果继承基类,则合并基类相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
//如果从容器得到Bean 定义信息,并且Bean 定义信息不是虚构的,
//则让工厂Bean 生产Bean 实例对象
boolean synthetic = (mbd != null && mbd.isSynthetic());
//调用FactoryBeanRegistrySupport 类的getObjectFromFactoryBean 方法,
//实现工厂Bean 生产Bean 对象实例的过程
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
在上面获取给定Bean 的实例对象的getObjectForBeanInstance() 方法中, 会调用FactoryBeanRegistrySupport 类的getObjectFromFactoryBean()方法,该方法实现了Bean 工厂生产Bean 实例对象。
Dereference(解引用):一个在C/C++中应用比较多的术语,在C++中,”*”是解引用符号,而”&”是引用符号,解引用是指变量指向的是所引用对象的本身数据,而不是引用对象的内存地址。
3、AbstractBeanFactory 生产Bean 实例对象
AbstractBeanFactory 类中生产Bean 实例对象的主要源码如下:
//Bean 工厂生产Bean 实例对象
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//Bean 工厂是单态模式,并且Bean 工厂缓存中存在指定名称的Bean 实例对象
if (factory.isSingleton() && containsSingleton(beanName)) {
//多线程同步,以防止数据不一致
synchronized (getSingletonMutex()) {
//直接从Bean 工厂缓存中获取指定名称的Bean 实例对象
Object object = this.factoryBeanObjectCache.get(beanName);
//Bean 工厂缓存中没有指定名称的实例对象,则生产该实例对象
if (object == null) {
//调用Bean 工厂的getObject 方法生产指定Bean 的实例对象
object = doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
} else {
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
//将生产的实例对象添加到Bean 工厂缓存中
this.factoryBeanObjectCache.put(beanName, object);
}
}
return object;
}
}
//调用Bean 工厂的getObject 方法生产指定Bean 的实例对象
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
//调用Bean 工厂的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 {
//调用BeanFactory 接口实现类的创建对象方法
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);
}
//创建出来的实例对象为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 实例对象的功能。
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");
}
@Override
public FactoryCreatedAnnotationTestBean getObject() throws Exception {
return this.instance;
}
//AnnotationTestBeanFactory 产生Bean 实例对象的实现
@Override
public Class<? extends IJmxTestBean> getObjectType() {
return FactoryCreatedAnnotationTestBean.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
其他的Proxy,RMI,JNDI 等等,都是根据相应的策略提供getObject()的实现。这里不做一一分析,这已经不是Spring 的核心功能,感兴趣的小伙可以再去深入研究。
再述autowiring
Spring IOC 容器提供了两种管理Bean 依赖关系的方式:
1)、显式管理:通过BeanDefinition 的属性值和构造方法实现Bean 依赖关系管理。
2)、autowiring:Spring IOC 容器的依赖自动装配功能,不需要对Bean 属性的依赖关系做显式的声明,只需要在配置好autowiring 属性,IOC 容器会自动使用反射查找属性的类型和名称,然后基于属性的类型或者名称来自动匹配容器中管理的Bean,从而自动地完成依赖注入。
通过对autowiring 自动装配特性的理解,我们知道容器对Bean 的自动装配发生在容器对Bean 依赖注入的过程中。在前面对Spring IOC 容器的依赖注入过程源码分析中,我们已经知道了容器对Bean 实例对象的属性注入的处理发生在AbstractAutoWireCapableBeanFactory 类中的populateBean()方法中,我们通过程序流程分析autowiring 的实现原理:
1、AbstractAutoWireCapableBeanFactory 对Bean 实例进行属性依赖注入
应用第一次通过getBean()方法(配置了lazy-init 预实例化属性的除外)向IOC 容器索取Bean 时,容器创建Bean 实例对象, 并且对Bean 实例对象进行属性依赖注入,AbstractAutoWireCapableBeanFactory 的populateBean()方法就是实现Bean 属性依赖注入的功能,其主要源码如下:
//将Bean 属性设置到生成的实例对象上
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
} else {
// Skip property population phase for null instance.
return;
}
}
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
//获取容器在解析Bean 定义资源时为BeanDefiniton 中设置的属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//对依赖注入处理,首先处理autowiring 自动装配的依赖注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//根据Bean 名称进行autowiring 自动装配处理
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//根据Bean 类型进行autowiring 自动装配处理
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//对非autowiring 的属性进行依赖注入处理
...
}
2、Spring IOC 容器根据Bean 名称或者类型进行autowiring 自动依赖注入
//根据类型对属性进行自动依赖注入
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取用户定义的类型转换器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
//存放解析的要注入的属性
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
//对Bean 对象中非简单属性(不是简单继承的对象,如8 中原始类型,字符
//URL 等都是简单属性)进行处理
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
//获取指定属性名称的属性描述器
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()) {
//获取属性的setter 方法
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);
//根据容器的Bean 定义解析依赖关系,返回所有要被注入的Bean 对象
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
//为属性赋值所引用的对象
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
//指定名称属性注册依赖Bean 名称,进行属性依赖注入
registerDependentBean(autowiredBeanName, beanName);
if (logger.isDebugEnabled()) {
logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
//释放已自动注入的属性
autowiredBeanNames.clear();
}
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
通过上面的源码分析,我们可以看出来通过属性名进行自动依赖注入的相对比通过属性类型进行自动依赖注入要稍微简单一些, 但是真正实现属性注入的是DefaultSingletonBeanRegistry 类的registerDependentBean()方法。
3、DefaultSingletonBeanRegistry 的registerDependentBean()方法对属性注入
//为指定的Bean 注入依赖的Bean
public void registerDependentBean(String beanName, String dependentBeanName) {
//处理Bean 名称,将别名转换为规范的Bean 名称
String canonicalName = canonicalName(beanName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) {
return;
}
// No entry yet -> fully synchronized manipulation of the dependentBeans Set
//多线程同步,保证容器内数据的一致性
//先从容器中:bean 名称-->全部依赖Bean 名称集合找查找给定名称Bean 的依赖Bean
synchronized (this.dependentBeanMap) {
//获取给定名称Bean 的所有依赖Bean 名称
dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
//为Bean 设置依赖Bean 信息
dependentBeans = new LinkedHashSet<>(8);
this.dependentBeanMap.put(canonicalName, dependentBeans);
}
//向容器中:bean 名称-->全部依赖Bean 名称集合添加Bean 的依赖信息
//即,将Bean 所依赖的Bean 添加到容器的集合中
dependentBeans.add(dependentBeanName);
}
//从容器中:bean 名称-->指定名称Bean 的依赖Bean 集合找查找给定名称Bean 的依赖Bean
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
if (dependenciesForBean == null) {
dependenciesForBean = new LinkedHashSet<>(8);
this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
}
//向容器中:bean 名称-->指定Bean 的依赖Bean 名称集合添加Bean 的依赖信息
//即,将Bean 所依赖的Bean 添加到容器的集合中
dependenciesForBean.add(canonicalName);
}
}
通过对autowiring 的源码分析,我们可以看出,autowiring 的实现过程:
a、对Bean 的属性代调用getBean()方法,完成依赖Bean 的初始化和依赖注入。
b、将依赖Bean 的属性引用设置到被依赖的Bean 属性上。
c、将依赖Bean 的名称和被依赖Bean 的名称存储在IOC 容器的集合中。
Spring IOC 容器的autowiring 属性自动依赖注入是一个很方便的特性,可以简化开发时的配置,但是凡是都有两面性,自动属性依赖注入也有不足,首先,Bean 的依赖关系在配置文件中无法很清楚地看出来,对于维护造成一定困难。其次,由于自动依赖注入是Spring 容器自动执行的,容器是不会智能判断的,如果配置不当,将会带来无法预料的后果,所以自动依赖注入特性在使用时还是综合考虑。