介绍Spring IOC 容器对 Bean 定 义资源的定位、读入和解析过程,同时也清楚了当用户通过 getBean 方法向 IOC 容器获取被管理的 Bean 时,IOC 容器对 Bean 进行的初始化和依赖注入过程,这些是 Spring IOC 容器的基本功能特性。 Spring IOC 容器还有一些高级特性,如使用 lazy-init 属性对 Bean 预初始化、FactoryBean 产生或者 修饰 Bean 对象的生成、IOC 容器初始化 Bean 过程中使用 BeanPostProcessor 后置处理器对 Bean 声明周 期事件管理和 IOC 容器的 autowiring 自动装配功能等。
Spring IOC 容器的 lazy-init 属性实现预实例化:IOC 容器的初始化过程就是对 Bean 定义 资源的定位、载入和注册,此时容器对 Bean 的依赖注入并没有发生,依赖注入主要是在应用程序第一 次向容器索取 Bean 时,通过 getBean 方法的调用完成。
当 Bean 定义资源的元素中配置了 lazy-init 属性时,容器将会在初始化的时候对所配置的 Bean 进行预实例化,Bean 的依赖注入在容器初始化的时候就已经完成。这样,当应用程序第一次向容器索取 被管理的 Bean 时,就不用再初始化和对 Bean 进行依赖注入了,直接从容器中获取已经完成依赖注入的 现成 Bean,可以提高应用第一次向容器获取 Bean 的性能。
下面我们通过代码分析容器预实例化的实现过程:
refresh()先从 IOC 容器的初始会过程开始,通过前面文章分析,我们知道 IOC 容器读入已经定位的 Bean 定义资 源是从 refresh 方法开始的,我们首先从 AbstractApplicationContext 类的 refresh 方法入手分析, 源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { destroyBeans(); cancelRefresh(ex); throw ex; } } }
在 refresh 方法中 ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory(); 启动了 Bean 定义资源的载入、注册过程,而 finishBeanFactoryInitialization 方法是对注册后的 Bean 定义中的预实例化(lazy-init=false,Spring 默认就是预实例化,即为 true)的 Bean 进行处理的地方。
finishBeanFactoryInitialization 处理预实例化 Bean当Bean定义资源被载入IOC容器之后,容器将Bean定义资源解析为容器内部的数据结构BeanDefinition 注册到容器中,AbstractApplicationContext 类中的 finishBeanFactoryInitialization 方法对配置了 预实例化属性的 Bean 进行预初始化过程,源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 protected void finishBeanFactoryInitialization (ConfigurableListableBeanFactory beanFactory) { 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)); } String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false , false ); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } beanFactory.setTempClassLoader(null ); beanFactory.freezeConfiguration(); beanFactory.preInstantiateSingletons(); }
ConfigurableListableBeanFactory 是一个接口,其 preInstantiateSingletons 方法由其子类 DefaultListableBeanFactory 提供。
DefaultListableBeanFactory 对配置 lazy-init 属性单态 Bean 的预实例化1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public void preInstantiateSingletons () throws BeansException { if (this .logger.isInfoEnabled()) { this .logger.info("Pre-instantiating singletons in " + this ); } List<String> beanNames; synchronized (this .beanDefinitionMap) { beanNames = new ArrayList<String>(this .beanDefinitionNames); } for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { 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(beanName); } } else { getBean(beanName); } } } }
通过对 lazy-init 处理源码的分析,我们可以看出,如果设置了 lazy-init 属性,则容器在完成 Bean 定义的注册之后,会通过 getBean 方法,触发对指定 Bean 的初始化和依赖注入过程,这样当应用第一 次向容器索取所需的 Bean 时,容器不再需要对 Bean 进行初始化和依赖注入,直接从已经完成实例化和 依赖注入的 Bean 中取一个现成的 Bean,这样就提高了第一次获取 Bean 的性能。
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 产生出来的对象。
FactoryBean 的源码如下1 2 3 4 5 6 7 8 9 10 public interface FactoryBean <T > { T getObject () throws Exception ; Class<?> getObjectType(); boolean isSingleton () ; }
AbstractBeanFactory 的 getBean 方法调用 FactoryBean在前面我们分析 Spring IOC 容器实例化 Bean 并进行依赖注入过程的源码时,提到在 getBean 方法触 发容器实例化 Bean 的时候会调用 AbstractBeanFactory 的 doGetBean 方法来进行实例化的过程,源码 如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 @SuppressWarnings("unchecked") protected <T> T doGetBean ( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null ) { if (logger.isDebugEnabled()) { 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 = getObjectForBeanInstance(sharedInstance, name, beanName, null ); } else { if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null ) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null ) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject () throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { Object prototypeInstance = null ; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this .scopes.get(scopeName); if (scope == null ) { throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'" ); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { public Object getObject () throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); 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; } } if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]" , ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 protected Object getObjectForBeanInstance ( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null ; if (mbd == null ) { object = getCachedObjectForFactoryBean(beanName); } if (object == null ) { FactoryBean<?> factory = (FactoryBean<?>) beanInstance; if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
在上面获取给定 Bean 的实例对象的 getObjectForBeanInstance 方法中,会调用 FactoryBeanRegistrySupport 类的 getObjectFromFactoryBean 方法,该方法实现了 Bean 工厂生产 Bean 实例对象。
Dereference(解引用):一个在 C/C中应用比较多的术语,在 C 中,*
是解引用符号,而&
是 引用符号,解引用是指变量指向的是所引用对象的本身数据,而不是引用对象的内存地址。
AbstractBeanFactory 生产 Bean 实例对象AbstractBeanFactory 类中生产 Bean 实例对象的主要源码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 protected Object getObjectFromFactoryBean (FactoryBean<?> factory, String beanName, boolean shouldPostProcess) { if (factory.isSingleton() && containsSingleton(beanName)) { synchronized (getSingletonMutex()) { Object object = this .factoryBeanObjectCache.get(beanName); if (object == null ) { object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess); this .factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT)); } return (object != NULL_OBJECT ? object : null ); } } else { return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 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 { object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { public Object run () throws Exception { return factory.getObject(); } }, acc); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { 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); } if (object == null && isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException( beanName, "FactoryBean which is currently in creation returned null from getObject" ); } 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; }
从上面的源码分析中,我们可以看出,BeanFactory 接口调用其实现类的 getObject 方法来实现创建 Bean 实例对象的功能
工厂 Bean 的实现类 getObject 方法创建 Bean 实例对象FactoryBean的实现类有非常多,比如:Proxy、RMI、JNDI、ServletContextFactoryBean等等,FactoryBean 接口为 Spring 容器提供了一个很好的封装机制,具体的 getObject 有不同的实现类根据不同的实现策 略来具体提供,我们分析一个最简单的 AnnotationTestFactoryBean 的实现源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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; } @Override public Class<? extends IJmxTestBean> getObjectType() { return FactoryCreatedAnnotationTestBean.class; } @Override public boolean isSingleton () { return true ; } }
其他的 Proxy,RMI,JNDI 等等,都是根据相应的策略提供 getObject 的实现。这里不做一一分析,这 已经不是 Spring 的核心功能,有需要的时候再去深入研究。
BeanPostProcessor 后置处理器的实现BeanPostProcessor 后置处理器是 Spring IOC 容器经常使用到的一个特性,这个 Bean 后置处理器是一 个监听器,可以监听容器触发的 Bean 声明周期事件。后置处理器向容器注册以后,容器中管理的 Bean 就具备了接收 IOC 容器事件回调的能力。
BeanPostProcessor 的使用非常简单,只需要提供一个实现接口 BeanPostProcessor 的实现类,然后在 Bean 的配置文件中设置即可。
BeanPostProcessor 的源码如下1 2 3 4 5 6 7 8 package org.springframework.beans.factory.config;import org.springframework.beans.BeansException;public interface BeanPostProcessor { Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException ; Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException ; }
这两个回调的入口都是和容器管理的 Bean 的生命周期事件紧密相关,可以为用户提供在 Spring IOC 容器初始化 Bean 过程中自定义的处理操作。
AbstractAutowireCapableBeanFactory 类对容器生成的 Bean 添加后置处理器BeanPostProcessor后置处理器的调用发生在Spring IOC容器完成对Bean实例对象的创建和属性的依 赖注入完成之后,在对 Spring 依赖注入的源码分析过程中我们知道,当应用程序第一次调用 getBean 方法(lazy-init 预实例化除外)向 Spring IOC 容器索取指定 Bean 时触发 Spring IOC 容器创建 Bean 实例对象并进行依赖注入的过程,其中真正实现创建 Bean 对象并进行依赖注入的方法是 AbstractAutowireCapableBeanFactory 类的 doCreateBean 方法,主要源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 protected Object doCreateBean (final String beanName, final RootBeanDefinition mbd, final Object[] args) { …… try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null ) { 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 方法。
initializeBean 方法为容器产生的 Bean 实例对象添加 BeanPostProcessor 后置处理器同样在 AbstractAutowireCapableBeanFactory 类中,initializeBean 方法实现为容器创建的 Bean 实例 对象添加 BeanPostProcessor 后置处理器,源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 protected Object initializeBean (final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null ) { AccessController.doPrivileged(new PrivilegedAction<Object>() { 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 { 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; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 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; } 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; }
BeanPostProcessor 是一个接口,其初始化前的操作方法和初始化后的操作方法均委托其实现子类来实 现,在 Spring 中,BeanPostProcessor 的实现子类非常的多,分别完成不同的操作,如:AOP 面向切面 编程的注册通知适配器、Bean 对象的数据校验、Bean 继承属性/方法的合并等等,我们以最简单的 AOP 切面织入来简单了解其主要的功能。
AdvisorAdapterRegistrationManager 在 Bean 对象初始化后注册通知适配器AdvisorAdapterRegistrationManager 是 BeanPostProcessor 的一个实现类,其主要的作用为容器中管 理的 Bean 注册一个面向切面编程的通知适配器,以便在 Spring 容器为所管理的 Bean 进行面向切面编 程时提供方便,其源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class AdvisorAdapterRegistrationManager implements BeanPostProcessor { private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance(); public void setAdvisorAdapterRegistry (AdvisorAdapterRegistry advisorAdapterRegistry) { this .advisorAdapterRegistry = advisorAdapterRegistry; } public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { return bean; } public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { if (bean instanceof AdvisorAdapter){ this .advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean); } return bean; } }
其他的 BeanPostProcessor 接口实现类的也类似,都是对 Bean 对象使用到的一些特性进行处理,或者 向 IOC 容器中注册,为创建的 Bean 实例对象做一些自定义的功能增加,这些操作是容器初始化 Bean 时 自动触发的,不需要认为的干预。
Spring IOC 容器 autowiring 实现原理Spring IOC 容器提供了两种管理 Bean 依赖关系的方式:
显式管理:通过 BeanDefinition 的属性值和构造方法实现 Bean 依赖关系管理。 autowiring:Spring IOC 容器的依赖自动装配功能,不需要对 Bean 属性的依赖关系做显式的声明,只需要在配置好 autowiring 属性,IOC 容器会自动使用反射查找属性的类型和名称,然后基于属性的类型或者名称来自动匹配容器中管理的 Bean,从而自动地完成依赖注入。 通过对 autowiring 自动装配特性的理解,我们知道容器对 Bean 的自动装配发生在容器对 Bean 依赖注 入的过程中。在前面对 Spring IOC 容器的依赖注入过程源码分析中,我们已经知道了容器对 Bean 实 例对象的属性注入的处理发生在 AbstractAutoWireCapableBeanFactory 类中的 populateBean 方法中, 我们通过程序流程分析 autowiring 的实现原理
AbstractAutoWireCapableBeanFactory 对 Bean 实例进行属性依赖注入应用第一次通过 getBean 方法(配置了 lazy-init 预实例化属性的除外)向 IoC 容器索取 Bean 时,容器 创建 Bean 实例对象,并且对 Bean 实例对象进行属性依赖注入,AbstractAutoWireCapableBeanFactory 的 populateBean 方法就是实现 Bean 属性依赖注入的功能,其主要源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 protected void populateBean (String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } } }
Spring IOC 容器根据 Bean 名称或者类型进行 autowiring 自动依赖注入:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 protected void autowireByName ( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { Object bean = getBean(propertyName); pvs.add(propertyName, bean); registerDependentBean(propertyName, beanName); if (logger.isDebugEnabled()) { logger.debug("Added autowiring by name from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + propertyName + "'" ); } } else { if (logger.isTraceEnabled()) { logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName + "' by name: no matching bean found" ); } } } } protected void autowireByType ( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { TypeConverter converter = getCustomTypeConverter(); if (converter == null ) { converter = bw; } Set<String> autowiredBeanNames = new LinkedHashSet<String>(4 ); String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { try { PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName); if (!Object.class.equals(pd.getPropertyType())) { MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd); boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass()); DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager); Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter); if (autowiredArgument != null ) { pvs.add(propertyName, autowiredArgument); } for (String autowiredBeanName : autowiredBeanNames) { 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 方法。
DefaultSingletonBeanRegistry 的 registerDependentBean 方法对属性注入1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public void registerDependentBean (String beanName, String dependentBeanName) { String canonicalName = canonicalName(beanName); synchronized (this .dependentBeanMap) { Set<String> dependentBeans = this .dependentBeanMap.get(canonicalName); if (dependentBeans == null ) { dependentBeans = new LinkedHashSet<String>(8 ); this .dependentBeanMap.put(canonicalName, dependentBeans); } dependentBeans.add(dependentBeanName); } synchronized (this .dependenciesForBeanMap) { Set<String> dependenciesForBean = this .dependenciesForBeanMap.get(dependentBeanName); if (dependenciesForBean == null ) { dependenciesForBean = new LinkedHashSet<String>(8 ); this .dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean); } dependenciesForBean.add(canonicalName); } }
通过对 autowiring 的源码分析,我们可以看出,autowiring 的实现过程:
对 Bean 的属性代调用 getBean 方法,完成依赖 Bean 的初始化和依赖注入。 将依赖 Bean 的属性引用设置到被依赖的 Bean 属性上。 将依赖 Bean 的名称和被依赖 Bean 的名称存储在 IOC 容器的集合中。 Spring IOC 容器的 autowiring 属性自动依赖注入是一个很方便的特性,可以简化开发时的配置,但是凡是都有两面性, 自动属性依赖注入也有不足,首先,Bean 的依赖关系在配置文件中无法很清楚地看出来,对于维护造成一定困难。其 次,由于自动依赖注入是 Spring 容器自动执行的,容器是不会智能判断的,如果配置不当,将会带来无法预料的后果, 所以自动依赖注入特性在使用时还是综合考虑。