一、Spring IoC容器的lazy-init属性实现预实例化
我们知道,当我们不使用lazy-init属性修饰bean时,这个bean对象将会在IOC容器初始化的时候就已经建立好,当我们
lazy-init=true时,则告诉容器初始化的时候不初始化这个bean实例,而是在我们getBean的时候再进行初始化,那么,IOC容器初始化时,是怎么样对lazy-init属性进行处理的呢?
首先回到IOC容器初始化的地方
1、IOC容器初始化refresh()
//容器初始化的过程,读入Bean定义资源,并解析注册
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();
//这里是对容器lazy-init属性进行处理的入口方法
finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
//销毁以创建的单态Bean
destroyBeans();
//取消refresh操作,重置容器的同步标识.
cancelRefresh(ex);
throw ex;
}
}
}
我们分析IOC容器初始化只是分析了obtainFreshBeanFactory()方法里面调用的refreshBeanFactory()方法,而对lazy-init属性的处理实在refresh()方法后面,也就是IOC容器先初始化完成,在finishBeanFactoryInitialization(beanFactory);进行对lazy-init属性的处理。lazy-init=false,Spring默认就是预实例化。
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));
}
//为了类型匹配,停止使用临时的类加载器
beanFactory.setTempClassLoader(null);
//缓存容器中所有注册的BeanDefinition元数据,以防被修改
beanFactory.freezeConfiguration();
//对配置了lazy-init属性的单态模式Bean进行预实例化处理
beanFactory.preInstantiateSingletons();
}
紧接着,调用preInstantiateSingletons进行预实例化 ,这个方法在DefaultListableBeanFactory类中实现
3、DefaultListableBeanFactory.preInstantiateSingletons()对配置lazy-init属性单态Bean的预实例化
//对配置lazy-init属性单态Bean的预实例化
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
//在对配置lazy-init属性单态Bean的预实例化过程中,必须多线程同步,以确保数据一致性
synchronized (this.beanDefinitionMap) {
for (String beanName : this.beanDefinitionNames) {
//获取指定名称的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(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();
}
if (isEagerInit) {
//调用getBean方法,触发容器对Bean实例化和依赖注入过程
getBean(beanName);
}
}
else {
//调用getBean方法,触发容器对Bean实例化和依赖注入过程
getBean(beanName);
}
}
}
}
}
通过上面的代码分析,可以知道
1、bean非抽象,且为单例模式
2、如果lazy-init=false,或者默认,则表示需要预实例化,则调用getBean()方法,先产生一个Bean实例对象,后面我们再去getBean时就直接从缓存中取,不再需要再去依赖注入一次。
3、不满足上述条件不处理。
二、FactoryBean
1、简介
在Spring中,有两个很容易混淆的类:BeanFactory和FactoryBean。
BeanFactory:Bean工厂,是一个工厂(Factory),我们Spring IoC容器的最顶层接口就是这个BeanFactory,它的作用是管理Bean,即实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
FactoryBean:工厂Bean,是一个Bean,作用是产生其他bean实例。通常情况下,这种bean没有什么特别的要求,仅需要提供一个工厂方法,该方法用来返回其他bean实例。通常情况下,bean无须自己实现工厂模式,Spring容器担任工厂角色;但少数情况下,容器中的bean本身就是工厂,其作用是产生其它bean实例。
当用户使用容器本身时,可以使用转义字符”&”来得到FactoryBean本身,以区别通过FactoryBean产生的实例对象和FactoryBean对象本身。
关于这FactoryBean,先来写个小例子:
创建一个User类,这里只有一个name属性
public class User {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
再创建一个UserFactoryBean,暂且叫它User的工厂bean,实现FactoryBean接口,先看下FactoryBean接口
//工厂Bean,用于产生其他对象
public interface FactoryBean<T> {
//获取容器管理的对象实例
T getObject() throws Exception;
//获取Bean工厂创建的对象的类型
Class<?> getObjectType();
//Bean工厂创建的对象是否是单态模式,如果是单态模式,则整个容器中只有一个实例
//对象,每次请求都返回同一个实例对象
boolean isSingleton();
}
public class UserFactoryBean implements FactoryBean {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Object getObject() throws Exception {
User user = new User();
user.setName(username);
return user ;
}
public Class getObjectType() {
// TODO Auto-generated method stub
return null;
}
public boolean isSingleton() {
// TODO Auto-generated method stub
return false;
}
}
UserFactory的逻辑很简单,就是注入进来的属性username,然后我们通过这个usernane去创建一个User的实例,达到一个工厂的目的,接下来配置xml文件
<bean id="userFactoryBean" class="com.errol.dao.UserFactoryBean">
<property name="username" value="Errol"></property>
</bean>
注意这里,配置文件只需要配置工厂bean,而不需要配置User,这个接口的方便之处就体现出来了,假设我们的User类有n个成员变量,以往的方式,我们需要一个个去配置,但是有了这个FactoryBean,我们赋值的过程放到了代码里面,配置就很简单。
接下来测试:
@Test
public void testFactoryBean(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println(context.getBean("userFactoryBean"));
System.out.println(context.getBean("userFactoryBean"));
System.out.println(context.getBean("&userFactoryBean"));
}
结果
com.errol.dao.User@554d7745
com.errol.dao.User@3313beb5
com.errol.dao.UserFactoryBean@e4865ce
上面可以发现,每次获取的bean值都不一样,前面两个获取到的是User对象,由于工厂类中的isSingleton我们返回的是false,也就是说默认User是prototype类型,所以,每次返回都不一样
而我们加了&符号,表示获取到UserFactoryBean对象本身,所以返回的是UserFactoryBean对象。而且默认是Singleton类型。
接下来我们来看看这个FactoryBean在实例化的时候是如何做的
2、AbstractBeanFactory的getBean方法调用FactoryBean
在分析Spring创建bean的实例对象,依赖注入的过程中,调用了AbstractBeanFactory的doGetBean方法来进行实例化的过程
//真正实现向IoC容器获取Bean的功能,也是触发依赖注入功能的地方
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
//如果指定的是别名,将别名转换为规范的Bean名称
final String beanName = transformedBeanName(name);
Object bean;
//先从缓存中取是否已经有被创建过的单态类型的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的相关处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
……
}
//获取给定Bean的实例对象,主要是完成FactoryBean的相关处理
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, 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方法中
1、会调用FactoryBeanRegistrySupport类的getObjectFromFactoryBean方法,该方法实现了Bean工厂生产Bean实例对象。
Dereference(解引用):一个在C/C++中应用比较多的术语,在C++中,”*”是解引用符号,而”&”是引用符号,解引用是指变量指向的是所引用对象的本身数据,而不是引用对象的内存地址。
再继续往下看
3、AbstractBeanFactory生产Bean实例对象:
getObjectFromFactoryBean方法的源码
//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, shouldPostProcess);
//将生产的实例对象添加到Bean工厂缓存中
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
return (object != NULL_OBJECT ? object : null);
}
}
//调用Bean工厂的getObject方法生产指定Bean的实例对象
else {
return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
}
}
//调用Bean工厂的getObject方法生产指定Bean的实例对象
private Object doGetObjectFromFactoryBean(
final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
//实现PrivilegedExceptionAction接口的匿名内置类
//根据JVM检查权限,然后决定BeanFactory创建实例对象
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
//调用BeanFactory接口实现类的创建对象方法
return 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 && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
//为创建出来的Bean实例对象添加BeanPostProcessor后置处理器
if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
}
}
return object;
}
总结:
1、首先判断FactoryBean是不是单例模式,单例模式直接从缓存的获取
2、产生bean的实例对象都调用了doGetObjectFromFactoryBean方法
3、该方法中调用了FactoryBean去产生我们的实例对象。
5、FactoryBean产生自身实例对象
这个过程就跟普通的bean产生没什么区别,区别在于,需要判断是否是FactoryBean的实现,beanName是不是以&开头就好了。
6、FactoryBean的应用
FactoryBean的实现类有非常多,比如:Proxy、RMI、JNDI、ServletContextFactoryBean等等,FactoryBean接口为Spring容器提供了一个很好的封装机制,具体的getObject有不同的实现类根据不同的实现策略来具体提供,Proxy,RMI,JNDI等等,都是根据相应的策略提供getObject的实现。
三、BeanPostProcessor后置处理器的实现
这个东西我们看到了很多次。
这个Bean后置处理器是一个监听器,可以监听容器触发的Bean声明周期事件。后置处理器向容器注册以后,容器中管理的Bean就具备了接收IoC容器事件回调的能力。
1、BeanPostProcessor的源码
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
public interface BeanPostProcessor {
//为在Bean的初始化前提供回调入口
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//为在Bean的初始化之后提供回调入口
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
这两个回调的入口都是和容器管理的Bean的生命周期事件紧密相关,可以为用户提供在Spring IoC容器初始化Bean过程中自定义的处理操作。
2、AbstractAutowireCapableBeanFactory类对容器生成的Bean添加后置处理器
BeanPostProcessor后置处理器的调用发生在Spring IoC容器完成对Bean实例对象的创建和属性的依赖注入完成之后,在对Spring依赖注入的源码分析过程中我们知道,当应用程序第一次调用getBean方法(lazy-init预实例化除外)向Spring IoC容器索取指定Bean时触发Spring IoC容器创建Bean实例对象并进行依赖注入的过程,其中真正实现创建Bean对象并进行依赖注入的方法是AbstractAutowireCapableBeanFactory类的doCreateBean方法
//真正创建Bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
//创建Bean实例对象
……
try {
//对Bean属性进行依赖注入
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//在对Bean实例对象生成和依赖注入完成以后,开始对Bean实例对象
//进行初始化 ,为Bean实例对象应用BeanPostProcessor后置处理器
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
……
//为应用返回所需要的实例对象
return exposedObject;
}
上面为Bean实例对象应用BeanPostProcessor后置处理器 initializeBean方法
3、AbstractAutowireCapableBeanFactory类的initializeBean方法
//初始容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
//JDK的安全机制验证权限
if (System.getSecurityManager() != null) {
//实现PrivilegedAction接口的匿名内部类
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
invokeAwareMethods(beanName, bean);
}
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);
}
//对BeanPostProcessor后置处理器的postProcessAfterInitialization
//回调方法的调用,为Bean实例初始化之后做一些处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
//调用BeanPostProcessor后置处理器实例对象初始化之前的处理方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//调用Bean实例所有的后置处理中的初始化前处理方法,为Bean实例对象在
//初始化之前做一些自定义的处理操作
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
//调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在
//初始化之后做一些自定义的处理操作
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
BeanPostProcessor是一个接口,其初始化前的操作方法和初始化后的操作方法均委托其实现子类来实现,在Spring中,BeanPostProcessor的实现子类非常的多,分别完成不同的操作,如:AOP面向切面编程的注册通知适配器、Bean对象的数据校验、Bean继承属性/方法的合并等等,我们以最简单的AOP切面织入来简单了解其主要的功能。
4、.AdvisorAdapterRegistrationManager在Bean对象初始化后注册通知适配器:
AdvisorAdapterRegistrationManager是BeanPostProcessor的一个实现类,其主要的作用为容器中管理的Bean注册一个面向切面编程的通知适配器,以便在Spring容器为所管理的Bean进行面向切面编程时提供方便,其源码如下:
//为容器中管理的Bean注册一个面向切面编程的通知适配器
public class AdvisorAdapterRegistrationManager implements BeanPostProcessor {
//容器中负责管理切面通知适配器注册的对象
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
this.advisorAdapterRegistry = advisorAdapterRegistry;
}
//BeanPostProcessor在Bean对象初始化前的操作
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//没有做任何操作,直接返回容器创建的Bean对象
return bean;
}
//BeanPostProcessor在Bean对象初始化后的操作
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时自动触发的,不需要人为的干预。
五、Spring IoC容器autowiring实现原理
Spring IOC为我们提供了两种管理Bean依赖关系的方式:
a、显示管理,也就是通过BeanDefinition属性和构造方法实现Bean的依赖管理
b、autowiring自动装配,不需要对bean属性进行显示的声明,也就是配置,只需要配置好autowiring属性,IOC容器将自动地按照规则(byName , byType)管理bean,从而完成注入。
通过对autowiring自动装配特性的理解,我们知道容器对Bean的自动装配发生在容器对Bean依赖注入的过程中。在前面对Spring IoC容器的依赖注入过程源码分析中,我们已经知道了容器对Bean实例对象的属性注入的处理发生在AbstractAutoWireCapableBeanFactory类中的populateBean方法中,我们通过程序流程分析autowiring的实现原理:
1、bstractAutoWireCapableBeanFactory对Bean实例进行属性依赖注入populateBean方法
protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
//获取Bean定义的属性值,并对属性值进行处理
PropertyValues pvs = mbd.getPropertyValues();
……
//对依赖注入处理,首先处理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);
}
}
//对非autowiring的属性进行依赖注入处理
……
}
上面分了三种情况,byName的autowiring注入属性,byType的autowiring注入属性,和非autowiring的注入
2、Spring IoC容器根据Bean名称或者类型进行autowiring自动依赖注入