通过之前对spring ioc的剖析,我们了解到:Spring IOC容器对Bean定义资源的定位、读入和解析y以及初始化和依赖注入过程,这些均属于容器的基本功能特性,接下来就容器的一些高级特性我们进行相应的学习。
1. 配置lazy-init属性实现预实例化
我们已经知道IOC容器的初始化过程就是对bean定义资源的定位、载入和注册,此时容器对bean的依赖注入并没有发生,此时:
bean的依赖注入:
- 发生时间:在应用程序第一次向容器索取bean时。
- 方式:通过getBean方法的调用完成。
但是如果当bean定义资源的<Bean>元素中配置了lazy-init属性后,容器将会在初始化时对所配置的bean进行预实例化,此时:
bean的依赖注入:
- 发生时间:容器初始化时已经完成。
- 方式:容器初始化。
- 当应用程序第一次向容器索取被管理的bean时,直接从容器中获取已经完成依赖注入的bean,提高了应用第一次向容器获取bean的性能。
接下来,通过剖析源码分析其实现过程:
首先从AbstractApplicationContext类的refresh方法开始:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//调用容器准备刷新的方法
prepareRefresh();
/**调用子类中refreshBeanFactory()方法
*启动Bean定义资源文件的过程
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//为BeanFactory配置容器特性
prepareBeanFactory(beanFactory);
try {
//为容器的子类指定事件处理器
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) {
destroyBeans();
cancelRefresh(ex);
throw ex;
}
}
}
其中:
//对容器lazy-init属性处理的入口方法
finishBeanFactoryInitialization(beanFactory);
此方法位于类AbstractApplicationContext中,是对配置了预实例化属性的bean进行预初始化过程,源码如下:
//对配置了lazy-init属性的bean进行预实例化处理
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));
}
beanFactory.setTempClassLoader(null);
//对容器中所有注册的BeanDefinition缓存,防止在预实例化过程中被修改
beanFactory.freezeConfiguration();
//对配置了lazy-init属性的单例模式下的bean进行预实例化处理
beanFactory.preInstantiateSingletons();
}
方法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不是抽象的,同时是单例模式的bean,
*并且lazy-init属性配置为false
*/
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//如果指定名称的bean是创建容器的bean
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 {
/*如果指定名称的bean不是创建容器的bean
*调用getBean方法,触发容器对bean实例化和依赖注入过程
*/
getBean(beanName);
}
}
}
}
}
经过上述分析:
如果设置了lazy-init属性,则容器在完成bean定义的注册之后,会通过getBean方法,触发对指定Bean的初始化和依赖注入过程。
当应用第一次向容器索取所需的bean时,容器不再需要对bean进行初始化和依赖注入,直接从已经完成实例化和依赖注入的bean中取一个线程的bean,提高了第一次获取bean的性能。
2. FactoryBean的实现
FactoryBean:
- 概念:工厂bean,本质也是bean。
- 作用:产生其他bean实例提供一个工厂方法,该方法用来返回其他bean实例。
源码如下:
//用于产生其他对象
public interface FactoryBean<T> {
//获取容器管理的对象实例
T getObject() throws Exception;
//获取Bean工厂创建的对象的类型
Class<?> getObjectType();
/*判断bean工厂创建的对象是否是单态模式,
*如果是单例模式,则整个容器中只有一个实例对象,
*每次请求都返回同一个实例对象
*/
boolean isSingleton();
}
类AbstractBeanFactory的doGetBean方法中使用FactoryBean:
//真正实现向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的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
.........................
}
方法getObjectForBeanInstance完成FactoryBean的相关处理:
//获取给定bean的实例对象,主要是完成FactoryBean的相关处理
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
/**容器得到了bean实例对象,这个实例对象可能是一个普通的bean,也可能是一个工厂bean,
*如果是一个工厂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);
}
/**如果对象为null,
*让Bean工厂生产给定名称的bean对象实例
*/
if (object == null) {
FactoryBean factory = (FactoryBean) beanInstance;
//如果从Bean工厂生产的bean是单例模式,则进行缓存
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
/**如果从容器得到bean定义信息,并且bean定义信息不是虚构的,
*则让工厂Bean生产bean实例对象
*/
boolean synthetic = (mbd != null && mbd.isSynthetic());
//调用方法getObjectFromFactoryBean实现工厂Bean生产bean对象实例的过程
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
注:
解引用:指所引用对象的本身数据。
类AbstractBeanFactory中方法getObjectFromFactoryBean实现工厂Bean生产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, 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);
}
}
方法doGetObjectFromFactoryBean调用方法getObject生产指定bean的实例对象:
//调用工厂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 {
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;
}
3. BeanPostProcessor后置处理器的实现
BeanPostProcessor后置处理器
- 名称:是一个监听器。
- 作用:监听容器触发的Bean声明周期事件。
- 影响:后置处理器向容器注册以后,容器中管理的bean就具备了接收IOC容器事件回调的能力。
- 使用方式:需要提供一个实现接口BeanPostProcessor的实现类,然后在Bean的配置文件中设置即可。
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对象并进行依赖注入的方法是AbstractAutowireCapableBeanFactory类的doCreateBean方法:
//真正创建bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
//创建bean实例对象
……
try {
//将bean实例对象封装,并且bean定义中配置的属性值赋值给实例对象
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//初始化bean对象
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方法:
//初始容器创建的bean实例对象,为其添加BeanPostProcessor后置处理器
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 {
//为bean实例对象包装相关属性
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
//回调方法的调用,为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;
}
其中,方法applyBeanPostProcessorsBeforeInitialization处理实例对象初始化之前
//调用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;
}
其中,方法applyBeanPostProcessorsAfterInitialization处理实例对象初始化之后
//调用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;
}
AdvisorAdapterRegistrationManager在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;
}
}
未完跟进中......(autowiring实现原理)
4. Spring IOC容器之autowiring实现原理
容器提供两种方式用来管理bean依赖关系:
- 显式管理:通过BeanDefinition的属性值和构造方法实现。
- autowiring:自动装配功能,不需对bean属性的依赖关系做显式声明,只需配置autowiring属性,容器将通过反射自动查找属性的类型和名称,之后基于属性的类型或名称自动匹配容器中的bean,自动完成依赖注入。
autowiring自动装配特性: 容器对Bean的自动装配发生在容器对Bean依赖注入的过程中。
而容器对bean实例对象的属性注入的处理发生在类AbstractAutoWireCapableBeanFactory中的方法populateBean中:
(1) 属性依赖注入
类AbstractAutoWireCapableBeanFactory的方法populateBean实现bean属性依赖注入的功能:
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的属性依赖注入
……
}
(2) 根据bean名称或类型进行autowiring自动依赖注入:
根据名称对属性进行自动依赖注入:
//根据名称对属性进行自动依赖注入
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//处理 bean对象中非简单属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
/**如果容器中包含指定名称的bean
*调用getBean方法向容器索取指定名称的bean实例,
*迭代触发对属性的初始化和依赖注入
*/
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
//指定名称属性注册依赖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);
//处理bean对象中非简单属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
//获取指定属性名称的属性描述器
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
//不对Object类型的属性进行autowiring自动依赖注入
if (!Object.class.equals(pd.getPropertyType())) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
//创建一个要被注入的依赖描述
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) {
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:
//为指定的bean注入依赖的bean
public void registerDependentBean(String beanName, String dependentBeanName) {
//处理bean名称
String canonicalName = canonicalName(beanName);
/**多线程同步,保证容器内数据的一致性
*根据bean名称,
*在全部依赖bean名称集合找查找给定名称bean的依赖bean
*/
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
dependentBeans = new LinkedHashSet<String>(8);
this.dependentBeanMap.put(canonicalName, dependentBeans);
}
//将bean所依赖的bean添加到容器的集合中
dependentBeans.add(dependentBeanName);
}
/**指定名称bean的依赖bean集合找查找给定名称
*bean的依赖bean
*/
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
if (dependenciesForBean == null) {
dependenciesForBean = new LinkedHashSet<String>(8);
this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
}
//将Bean所依赖的Bean添加到容器的集合中
dependenciesForBean.add(canonicalName);
}
}
autowiring的实现过程:
- 通过对bean的属性迭代调用getBean方法,完成依赖bean的初始化和依赖注入。
- 将依赖bean的属性引用设置到被依赖的bean属性上。
- 将依赖bean的名称和被依赖bean的名称存储在容器集合中。
autowiring属性自动依赖注入是一个很方便的特性,可简化开发时的配置,但自动属性依赖注入也有不足。
autowiring属性自动依赖注入的不足:
- bean的依赖关系在配置文件中并不具有易读性,不利于维护造成一定困难。
- 将依赖注入交给容器自动执行,若配置不当,后果无法评估。
网友评论