spring源码--10--IOC高级特性--autowiring实现原理

spring源码–10–IOC高级特性–autowiring实现原理

1、Spring IoC容器提供了2种方式 管理Bean的依赖关系

1.1、显式管理

通过BeanDefinition的属性值和构造方法实现Bean依赖关系管理。

1.2、autowiring(自动装配)

不需要对Bean属性的依赖关系做显式的声明,只需要在配置好autowiring属性,IoC容器会自动使用反射查找属性的类型和名称,然后基于属性的类型或者名称来自动匹配容器中管理的Bean,从而自动地完成依赖注入。

对Bean的自动装配发生在容器对Bean依赖注入的过程中。具体在AbstractAutoWireCapableBeanFactory.populateBean()方法中,我们通过源码分析autowiring的实现原理。

2、自动装配 源码



public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {


    /**
     * 使用 RootBeanDefinition的属性值 填充给定 BeanWrapper 中的bean实例。
     *
     * @param beanName the name of the bean
     * @param mbd the bean definition for the bean
     * @param bw   BeanWrapper with bean instance
     */
    @SuppressWarnings("deprecation") // for postProcessPropertyValues
    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
 

			.
			.
			.
            // 对autowire自动装配的处理,根据Bean名称自动装配注入
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
            // Add property values based on autowire by type if applicable.
            // 根据Bean类型自动装配注入
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
			.
			.
			.
					
	}
	
	
	
	//根据Bean名称自动装配注入
	protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		 //对Bean对象中非简单属性(不是简单继承的对象,如原始类型,字符串,URL等//都是简单属性)进行处理  
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			 //如果Spring IOC容器中包含指定名称的Bean  
			if (containsBean(propertyName)) {
				
				//调用getBean方法向IoC容器索取指定名称的Bean实例,迭代触发属性的初始化和依赖注入  
				Object bean = getBean(propertyName);
				//为指定名称的属性赋予属性值  
				pvs.add(propertyName, bean);
				//指定名称属性注册依赖Bean名称,进行属性依赖注入
				//真正依赖注入的地方
				registerDependentBean(propertyName, beanName);
				if (logger.isTraceEnabled()) {
					logger.trace("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");
				}
			}
		}
	}

   // 根据Bean类型自动装配注入
	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 = !(bw.getWrappedInstance() instanceof PriorityOrdered);
					//创建一个要被注入的依赖描述   
					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.isTraceEnabled()) {
							logger.trace("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);
			}
		}
	}

 



}


3、DefaultSingletonBeanRegistry.registerDependentBean 源码

真正实现属性注入的是DefaultSingletonBeanRegistry.registerDependentBean方法

3.1、源码


public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {


	//为指定的Bean注入依赖的Bean 
	public void registerDependentBean(String beanName, String dependentBeanName) {
		//处理Bean名称,将别名转换为规范的Bean名称  
		String canonicalName = canonicalName(beanName);
		//多线程同步,保证容器内数据的一致性  
		//先从容器中: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;
			}
		}
		//从容器中:bean名称-->指定名称Bean的依赖Bean集合中 查找给定名称  		
		synchronized (this.dependenciesForBeanMap) {
			Set<String> dependenciesForBean =
					this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
					
			//向容器中:bean名称-->指定Bean的依赖Bean名称集合添加Bean的依赖信息  
			//即,将Bean所依赖的Bean添加到容器的集合中  
			dependenciesForBean.add(canonicalName);
		}
	}
	
	
}

4、总结

通过对autowiring的源码分析,我们可以看出,autowiring的实现过程:

1. 对Bean的属性迭代调用getBean方法,完成依赖Bean的初始化和依赖注入。
2. 将依赖Bean的属性引用设置到被依赖的Bean属性上。
3. 将依赖Bean的名称和被依赖Bean的名称存储在IoC容器的集合中。

4.1、缺点

  1. Bean的依赖关系在配置文件中无法很清楚地看出来,对于维护造成一定困难。
  2. 由于自动依赖注入是Spring容器自动执行的,容器是不会智能判断的,如果配置不当,将会带来无法预料的后果

4.2、优点

简化开发配置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值