spring源码学习---@Autowired 注入源码分析和自定义依赖注入

 一、简介

      众所周知,Spring的依赖注入(DI)对Spring IOC 有着举足轻重的作用,是Spring灵魂所在。本篇文章就从日常开发中最常用的注解@Autowired开始,着手分析Spring是如何通过它们将Bean所需的外部资源注入其中.

1.1、@Autowired 注入规则

 @Autowired可以应用在 非静态字段、非静态方法、构造器上面注入bean。

1.2、 @Autowired 注入过程

  1.       元信息解析
  2.       依赖查找
  3.       依赖注入(字段、方法)

1.3、代码准备

@Configuration
public class AnnotationDependencyInjectionResolutionDemo {

    // DependencyDescriptor ->
    // 必须(required=true)
    // 实时注入(eager=true)
    // 通过类型(User.class)
    // 字段名称("user")
    // 是否首要(primary = true)
    @Autowired(required = false)         // 依赖查找(处理)
    private User user;
    
    public static void main(String[] args) {

        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类) -> Spring Bean
        applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);

        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);

        String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
        // 加载 XML 资源,解析并且生成 BeanDefinition
        beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);

        // 启动 Spring 应用上下文
        applicationContext.refresh();

        // 依赖查找 QualifierAnnotationDependencyInjectionDemo Bean
        AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);

        // 期待输出 superUser Bean
        System.out.println("demo.user = " + demo.user);
        applicationContext.close();

    }
}

xml中的

 
       
       
       
       
   

二、源码分析

2.1 @Autowired的定义

首先,我们看@Autowired的定义里可以发现,它是通过AutowiredAnnotationBeanPostProcessor去实现解析的

 /*
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @author Sam Brannen
 * @since 2.5
 * @see AutowiredAnnotationBeanPostProcessor
 * @see Qualifier
 * @see Value
 */
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	/**
	 * Declares whether the annotated dependency is required.
	 * 

Defaults to {@code true}. */ boolean required() default true; }

2.2 AutowiredAnnotationBeanPostProcessor

在看一下AutowiredAnnotationBeanPostProcessor它的继承图表:

spring源码学习---@Autowired 注入源码分析和自定义依赖注入_第1张图片

由此继承图标我们能得出如下结论:

  • 实现了BeanPostProcessor,所以介入到Bean的初始化前后
  • 实现了InstantiationAwareBeanPostProcessor接口,所以可以介入到Bean的实例化前后
  • 实现了MergedBeanDefinitionPostProcessor,说明它可以合并bean的定义信息(用来合并parent="user" 父类中属性)
  • 实现了BeanFactoryAware(BeanFactory的回调)
  • 实现了PriorityOrdered(排序)

2.3、第一阶段:元信息解析

    解析@Resource注解的不是这个类,而是CommonAnnotationBeanPostProcessor,但本文只会以AutowiredAnnotationBeanPostProcessor为例做深入分析~~~(解析@Autowired

2.3.1、AutowiredAnnotationBeanPostProcessor 中属性

// 该处理器支持解析的注解们~~~(这里长度设置为4)
	// 默认支持的是3个(当然你可以自己添加自定义的依赖注入的注解   这点非常强大)
	private final Set> autowiredAnnotationTypes = new LinkedHashSet<>();

	// @Autowired(required = false)这个注解的属性值名称
	private String requiredParameterName = "required";

	// 这个值一般请不要改变(若改成false,效果required = false的作用是相反的了)
	private boolean requiredParameterValue = true;

	private int order = Ordered.LOWEST_PRECEDENCE - 2;

	@Nullable
	private ConfigurableListableBeanFactory beanFactory;

	// 对@Lookup方法的支持  本文不讨论
	private final Set lookupMethodsChecked = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
	// 构造函数注入,本文也不讨论
	private final Map, Constructor[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);

	// 方法注入、字段filed注入  本文的重中之重
	// 此处InjectionMetadata这个类非常重要,到了此处@Autowired注解含义已经没有了,完全被准备成这个元数据了
	//  所以方便我们自定义注解的支持~~~优秀
	// InjectionMetadata持有targetClass、Collection injectedElements等两个重要属性
	// 其中InjectedElement这个抽象类最重要的两个实现为:AutowiredFieldElement和AutowiredMethodElement
	private final Map injectionMetadataCache = new ConcurrentHashMap<>(256);

2.3.2、构造方法(也是唯一的一个构造方法)

     AutowiredAnnotationBeanPostProcessor执行构造方法时集合autowiredAnnotationTypes中依次放入了三个注解类@Autowired、@Value和JSR-330标准的@Inject

    // 这是它唯一构造函数  默认支持下面三种租借(当然@Inject需要额外导包)
	// 请注意:此处@Value注解也是被依赖注入解析的~~~~~~~~
	// 当然如果你需要支持到你的自定义注解,你还可以调用下面的set方法添加。
	@SuppressWarnings("unchecked")
	public AutowiredAnnotationBeanPostProcessor() {
		//后置处理器将处理@Autowire注解
		this.autowiredAnnotationTypes.add(Autowired.class);
		//后置处理器将处理@Value注解
		this.autowiredAnnotationTypes.add(Value.class);
		try {
			//后置处理器将处理javax.inject.Inject JSR-330注解
			this.autowiredAnnotationTypes.add((Class)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

2.3.4 setAutowiredAnnotationType 是用于实现自定义依赖注入注解类型

      两个setAutowiredAnnotationType是用于实现自定义依赖注入注解类型,首先它会把autowiredAnnotationTypes里面的元素全部clear,然后加入自定义的依赖注入注解类型,所以我们要注意在实现自定义注解注入时,这里会先把默认的注解类型清除

/**
	 *  这两个setAutowiredAnnotationType是用于实现自定义依赖注入注解类型,
	 *  首先它会把autowiredAnnotationTypes里面的元素全部clear,
	 * 然后加入自定义的依赖注入注解类型,所以我们要注意在实现自定义注解注入时,这里会先把默认的注解类型清除
	 */
	public void setAutowiredAnnotationType(Class autowiredAnnotationType) {
		Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
		this.autowiredAnnotationTypes.clear();
		this.autowiredAnnotationTypes.add(autowiredAnnotationType);
	}

2.3.5 postProcessMergedBeanDefinition(核心)

    第一个非常重要的核心方法,它负责:
         1、解析@Autowired等注解然后转换
         2、把注解信息转换为InjectionMetadata然后缓存到上面的injectionMetadataCache里面
    postProcessMergedBeanDefinition的执行时机非常早,在doCreateBean()前部分完成bean定义信息的合并

 // 第一个非常重要的核心方法~~~  
	//它负责1、解析@Autowired等注解然后转换
	// 2、把注解信息转换为InjectionMetadata然后缓存到上面的injectionMetadataCache里面
	// postProcessMergedBeanDefinition的执行时机非常早,在doCreateBean()前部分完成bean定义信息的合并
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
 

// 方法名为查找到该bean的依赖注入元信息,内部只要查找到了就会加入到缓存内,下次没必要再重复查找了~
	// 它是一个模版方法,真正做事的方法是:buildAutowiringMetadata
	// 它复杂把标注有@Autowired注解的属性转换为Metadata元数据信息  从而消除注解的定义
	// 此处查找包括了字段依赖注入和方法依赖注入~~~
	//获取给定类的autowire相关注解元信息
	private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz, @Nullable PropertyValues pvs) {
		// Fall back to class name as cache key, for backwards compatibility with custom callers.
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
		//首先从容器中查找是否有给定类的autowire相关注解元信息
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						//解析给定类autowire相关注解元信息
						metadata.clear(pvs);
					}
					//解析给定类autowire相关注解元信息
					metadata = buildAutowiringMetadata(clazz);
					//将得到的给定类autowire相关注解元信息存储在容器缓存中
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

// 这里我认为是整个依赖注入前期工作的精髓所在,简单粗暴的可以理解为:
	 // 它把以依赖注入都转换为InjectionMetadata元信息,待后续使用
	// 这里会处理字段注入、方法注入~~~
	// 注意:Autowired使用在static字段/方法上、0个入参的方法上(不会报错 只是无效)
	// 显然方法的访问级别、是否final都是可以正常被注入进来的~~~
	//解析给定类autowire相关注解元信息
	private InjectionMetadata buildAutowiringMetadata(final Class clazz) {
		//创建一个存放注解元信息的集合
		LinkedList elements = new LinkedList<>();
		Class targetClass = clazz;

		//递归遍历当前类及其所有基类,解析全部注解元信息
		do {
			//创建一个存储当前正在处理类注解元信息的集合
			final LinkedList currElements = new LinkedList<>();

			//利用JDK反射机制获取给定类中所有的声明字段,获取字段上的注解信息
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				//获取给定字段上的注解
				AnnotationAttributes ann = findAutowiredAnnotation(field);
				if (ann != null) {
					//如果给定字段是静态的(static),则直接遍历下一个字段
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					//判断注解的required属性值是否有效
					boolean required = determineRequiredStatus(ann);
					//将当前字段元信息封装,添加在返回的集合中
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			//利用JDK反射机制获取给定类中所有的声明方法,获取方法上的注解信息
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				//获取给定方法上的所有注解
				AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					//如果方法是静态的,则直接遍历下一个方法
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					//如果方法的参数列表为空
					if (method.getParameterCount() == 0) {
						if (logger.isWarnEnabled()) {
							logger.warn("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					//判断注解的required属性值是否有效
					boolean required = determineRequiredStatus(ann);
					//获取当前方法的属性描述符,即方法是可读的(readable)getter方法,还是可写的(writeable)setter方法
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					//将方法元信息封装添加到返回的元信息集合中
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			//将当前类的注解元信息存放到注解元信息集合中
			elements.addAll(0, currElements);
			//获取给定类的父类
			targetClass = targetClass.getSuperclass();
		}
		//如果给定类有基类,并且基类不是Object,则递归获取其基类的元信息
		while (targetClass != null && targetClass != Object.class);

		return new InjectionMetadata(clazz, elements);
	}

    这一步,借助postProcessMergedBeanDefinition()方法完成了对该bean中所有的依赖注入的属性、方法及其父类的属性、方法进行合并Mergerd完成了原始元信息的转换,已经把依赖注入的相关注解全都转换成了InjectionMetadata,这样后面的使用过程中将不再需要再和具体注解打交道,而是做着一些和业务无关的动作即可。接下来进入注入阶段

2.4、注入阶段

      这是核心阶段,也是最为复杂的阶段,当然前面的解析已经为本步骤做好了元数据的铺垫。

     我们知道在Bean的创建过程中,完成Bean的实例化后,会调用方法AbstractAutowireCapableBeanFactory#populateBean()完成对Bean的属性赋值,从而就会触发InstantiationAwareBeanPostProcessor.postProcessPropertyValues()方法给属性进行赋值,这处也就是本步骤的入口。

    围绕着这个模板方法postProcessPropertyValues, 我们回到AutowiredAnnotationBeanPostProcessor,找到postProcessPropertyValues的重写: 

//处理类中的属性
	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

		//获取指定类中autowire相关注解的元信息
		// 从缓存中取出这个bean对应的依赖注入的元信息
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			//对Bean的属性进行自动注入
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		}
		return pvs;
	}

      综上能够发现核心InjectionMetadata#inject(),最终依赖注入实际做事的是InjectedElement,这个抽象类有好几个实现,此处我们以使用最为广泛的AutowiredFieldElement进行说明

2.4.1、AutowiredFieldElement实现属性依赖注入

       这个类继承自静态抽象内部类InjectionMetadata.InjectedElement,并且它还是AutowiredAnnotationBeanPostProcessor的private内部类,体现出非常高的内聚性

		// 它的宿主类是AutowiredAnnotationBeanPostProcessor 高内聚低耦合
	private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {

		private final boolean required;
		private volatile boolean cached = false;
		@Nullable
		private volatile Object cachedFieldValue;

		//唯一构造方法
		public AutowiredFieldElement(Field field, boolean required) {
			super(field, null); // 此处显示调用父类的构造函数
			this.required = required;
		}

		// 核心方法:字段的依赖注入
		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			// 显然此处父类的member就指的是filed
			Field field = (Field) this.member;
			Object value;
		
			// 走缓存,关于cachedFieldValue的值  且听下文分解
			if (this.cached) {
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			} else {
				// 每个Field都包装成一个DependencyDescriptor
				// 如果是Method包装成DependencyDescriptor,毕竟一个方法可以有多个入参
				// 此处包装成它后,显然和元数据都无关了,只和Field有关了  完全隔离
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				// 转换器使用的bean工厂的转换器~~~
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					// 获取依赖的value值的工作  最终还是委托给beanFactory.resolveDependency()去完成的~~~~
					// 这个接口方法由AutowireCapableBeanFactory提供,它提供了从bean工厂里获取依赖值的能力~
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				} catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}

				// 下面代码是把缓存值缓存起来  让同一个Field注入多次能提高效率
				synchronized (this) {
					if (!this.cached) {
				
						// 可以看到value!=null并且required=true才会进行缓存的处理
						// 按照上例 此处value值为A@2277实例
						if (value != null || this.required) {
							this.cachedFieldValue = desc; // 可以看到缓存的值是上面的DependencyDescriptor对象~~~~


							// 这个方法是宿主类AutowiredAnnotationBeanPostProcessor的方法
							// 简单的说就是注册到bean工厂去,比如此处b是依赖a的  所以就注册这个依赖关系进去了
							// 参考this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
							registerDependentBeans(beanName, autowiredBeanNames);

							// autowiredBeanNames里可能会有别名的名称~~~所以size可能大于1
							if (autowiredBeanNames.size() == 1) {

								// beanFactory.isTypeMatch挺重要的~~~~因为@Autowired是按照类型注入的
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
									this.cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());
								}
							}
						} else {
							this.cachedFieldValue = null;
						}
						this.cached = true;
					}
				}
			}
	
			// 不为null,就完成最终的set值  利用反射给filed属性赋值~~~~
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}

前面准备好的注解的、需要注入的元数据信息,这一步使用执行注入。
从源码中也能发现一个特点,Spring大量的使用到了转换、适配、委托等机制。因此最终最最最重要的一行代码无非是这一句:

//根据容器中Bean定义,解析指定的依赖关系,获取依赖对象
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

委托AutowireCapableBeanFactory来获取到依赖值value,从而最终完成注入(反射执行注入~)。
so,其实最核心还是在Bean工厂里,也就是它的唯一内建实现类DefaultListableBeanFactory。

2.4.2、DefaultListableBeanFactory解析依赖值

  我们跟进这里的beanFactory.resolveDependency,进入DefaultListableBeanFactory, 这个方法有个重要的入参DependencyDescriptor:

/**
 * Descriptor for a specific dependency that is about to be injected.
 * Wraps a constructor parameter, a method parameter or a field,
 * allowing unified access to their metadata.
 *
 * @author Juergen Hoeller
 * @since 2.5
 */
@SuppressWarnings("serial")
public class DependencyDescriptor extends InjectionPoint implements Serializable {
	
	//被申明的类,也就是注入的容器
	private final Class declaringClass;

	@Nullable //方法注入名  这里可为空 因为不都是方法注入
	private String methodName;

	@Nullable //参数类型
	private Class[] parameterTypes;
	
	//参数索引顺序
	private int parameterIndex;

	@Nullable //字段注入的字段名
	private String fieldName;
	
	//是否必需
	private final boolean required;
	
	//是否是饥饿的 对应@Lazy
	private final boolean eager;
	
	//嵌入层次
	private int nestingLevel = 1;

	@Nullable
	private Class containingClass;

	@Nullable //类型处理
	private transient volatile ResolvableType resolvableType;

	@Nullable//类型描述  描述类型相关的内容
	private transient volatile TypeDescriptor typeDescriptor;

通过DependencyDescriptor 的每个描述字段可以大致猜到注入的user依赖对应的相关描述

 // DependencyDescriptor ->
    // 必须(required=true)
    // 实时注入(eager=true)
    // 通过类型(User.class)
    // 字段名称("user")
    // 是否首要(primary = true)
    @Autowired(required = false)         // 依赖查找(处理)
    private User user;

在resolveDependency里面debug, 观察DependencyDescriptor 里的值和猜测的基本一致 :
spring源码学习---@Autowired 注入源码分析和自定义依赖注入_第2张图片

回到resolveDependency方法:

@Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        //此处使用的是DefaultParameterNameDiscoverer 来获取参数名
		// 这就是为什么我们使用@Autowired注入,
		// 即使有多个同类型的Bean,也可以通过field属性名进行区分的根本原因(可以不需要使用@Qualifier注解)
		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		// 支持Optional  原来还是doResolveDependency  暂略
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		//支持ObjectFactory和ObjectProvider(延迟注入)
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
			// 绝大部分情况下  肯定走到这里~~~~
			// 此处特别特别的需要重视:这是@Lazy支持的根本原因~~
			// 关于AutowireCandidateResolver我建议小伙伴先看下一个章节~~~
			// 此处若通过AutowireCandidateResolver解析到了值就直接返回了(若标注了@Lazy,此处的result将不会为null了~~~)
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
			// doResolveDependency是绝大多数情况下  最终会去执行的代码(若result仍旧为null的话)
			if (result == null) {
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

重中之重)
绝大多数情况下,肯定会经由我们的doResolveDependency()方法来处理,因此这个方法的实现才是重中之重。其实getLazyResolutionProxyIfNecessary()它的底层依赖还是doResolveDependency()这个方法

看看DefaultListableBeanFactory对这个"重中之重"的实现:
 

// 此处autowiredBeanNames是在inject的一个空的Set
    // autowired表示最终可以注入进去的bean名称们(因为可能是会有多个符合条件的)
	@Nullable
	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
       //这个方法是通过依赖描述符处理注入多次嵌套
		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			Class type = descriptor.getDependencyType();
			// 拿到@Value注解的value值(是个字符串)  若没有标注@Value  显然就不用那啥了
			// 从此处其实也可以看出,@Value注解的优先级对于找到bean来说还是蛮高的
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			// ============ 这部分主要是解析@Value注解
			// 解析它的占位符,解析它的SpEL表达式
			// 相关处理类曹靠BeanExpressionResolver和StandardBeanExpressionResolver  StandardEvaluationContext等
			// 因为关于@Value的文章里详细解过,此处一笔带过~~~
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				return (descriptor.getField() != null ?
						converter.convertIfNecessary(value, type, descriptor.getField()) :
						converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
			}

			// 此处处理的是多值注入的情况,比如注入Stream、Map、Array、Collection等等  Spring都是支持的
			// 需要稍微注意一点,Stream这种类型的注入在Spring4以上才得到支持的
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			// 显然绝大部分情况下,都会走到这里(因为大部分我们都是单值注入~)
			// findAutowireCandidates可以说又是整个依赖注入的灵魂之一~~~~ 它的查找步骤简述如下:
			//1、BeanFactoryUtils.beanNamesForTypeIncludingAncestors()
			//   找到这种类型的所有的beanNames(candidateNames)(可能有多个哟,但大多数情况下只有一个)
			//2、处理resolvableDependencies比如ApplicationContext的依赖,让他们也能够正常注入进去(他们可不作为bean存在容器里~)
			//3、遍历candidateNames:检查它是否可以被依赖、容器内是否存在bean定义(或者Singleton)
			//      若符合,getBean()出来放在map里
			//4、若返回的Map不为Empty()了,直接return  表示找到了(当然还可能是多个~~)
			//     若返回的还是Empty,那就继续检查requiredType是否为Map、Collection等类型,
			//      从它里面去找。。。(这种注入case使用太少,此处暂略~)
			Map matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;
            // 若有多个匹配
			// 需要注意的是:@Qualifier注解在上面就已经生效了~~~~
			// 因为AutowireCandidateResolver.isAutowireCandidate是在上面生效的
			if (matchingBeans.size() > 1) {
				// 1、是否标注有@Primary  有这种bean就直接返回(@Primary只允许标注在一个同类型Bean上)
				// 2、看是否有标注有`javax.annotation.Priority`这个注解的
				// 3、根据字段field名,去和beanName匹配  匹配上了也行(这就是为何我们有时候不用@Qulifier也没事的原因之一)
				// 此处注意:descriptor.getDependencyName()这个属性表示字段名,
				// 靠的是`DefaultParameterNameDiscoverer`去把字段名取出来的~
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(type, matchingBeans);
					}
					else {
						// In case of an optional Collection/Map, silently ignore a non-unique case:
						// possibly it was meant to be an empty collection of multiple regular beans
						// (before 4.3 in particular when we didn't even look for collection beans).
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				// 只有一个匹配就啥都说了  干就完了
				// We have exactly one match.
				Map.Entry entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
				// 此处getBean() 拿到该类型的实例对象了~~~
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			//设置到当前的注入点
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

    其实本类的doResolveDependency()方法使用非常的广泛,虽然不属于接口方法,但是在DefaultListableBeanFactory类中还是public的访问权限。

 2.5、总结

       Spring使用了大量的委托代理还有模板方法等,实现了高内聚低耦合的特点。整个对@Autowired依赖注入的流程分为两个周期,第一个是解析元信息并放入缓存中,第二个周期是注入

         每个阶段有每个阶段的核心,解析元信息核心是模仿双亲委派的父类优先的原则去合并BeanDefition, 并全部转换成InjectionMetadata, 第二个阶段就是InjectionMetadata的inject方法的实现,其中会涉及到beanFactory.resolveDependency,这里可以处理多种注入类型的封装,包括Optional、ObjectFactory、ObjectProvider和jsr330 里面的依赖注入方案,最后处理默认注入操作,最终通过反射将值设置到字段当中。

三、Java通用注解注入原理

   与@Autowired等效的@Resource注解虽然注入效果一样,但是是通过另一个BeanPostProcessor–CommonAnnotationBeanPostProcessor去实现的,实现流程大同小异,提供对jdk注入注解和ejb WebServiceRef等注入注解的支持。

  CommonAnnotationBeanPostProcessor 调用优先级高于AutowiredAnnotationBeanPostProcessor。

四、自定义依赖注入注解

基于AutowiredAnnotationBeanPostProcessor 实现
自定义实现 

 • 生命周期处理 
        • InstantiationAwareBeanPostProcessor 
        • MergedBeanDefinitionPostProcessor 
    • 元数据 
        • InjectedElement 
        • InjectionMetadata

4.1、第一种实现:直接继承@Autowired注解

/**
 * 自定义注解(元标注 @Autowired)
 *
 * @author 
 * @since
 */
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Autowired
public @interface MyAutowired {

    /**
     * Declares whether the annotated dependency is required.
     * 

Defaults to {@code true}. */ boolean required() default true; }

4.2、通过、AutowiredAnnotationBeanPostProcessor

/**
 * 自定义依赖注入注解
 *
 * @author
 * @since
 */
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InjectedUser {
}
   //注意这里要设置成static,不然依赖注入会失效,
    // 因为这个AutowiredAnnotationBeanPostProcessor定义在当前demo类中,
    // 想要拿到自定义的AutowiredAnnotationBeanPostProcessor,就必须实例化demo类 
    //但是在实例化demo类LeonAutowired也同时被处理了,
    // 此时还没有自定义的AutowiredAnnotationBeanPostProcessor,因此不认识@LeonAutowired,
    //因此被注入了null。然后等实例化完了之后自定义的AutowiredAnnotationBeanPostProcessor才拿到
    @Bean
    @Order(Ordered.LOWEST_PRECEDENCE - 3)
    @Scope
    public static AutowiredAnnotationBeanPostProcessor beanPostProcessor() {
        AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        beanPostProcessor.setAutowiredAnnotationType(InjectedUser.class);
        return beanPostProcessor;
    }

 

 

 

你可能感兴趣的:(spring源码学习)