Spring依赖注入中,@Autowired字段注入的源码解析

前言

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

准备

先定义一个要注入的类

public class WakingLeon{
    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static WakingLeon createLeon() {
        return new WakingLeon();
    }

    @Override
    public String toString() {
        return "WakingLeon{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

然后我们新建一个被注入的类AutowiredAnnotationInjectionDemo,用@Bean的方式定义一个Bean(也可以用xml去配置)

	@Bean
    public WakingLeon wakingLeon(){
        WakingLeon wakingLeon = new WakingLeon();
        wakingLeon.setId(1L);
        wakingLeon.setName("Leon");
        return wakingLeon;
    }

我们通过main中自定义上下文的方式演示:

public static void main(String[] args) {
        //新建一个容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //将当前被注入的类注册到容器中
        applicationContext.register(AutowiredAnnotationInjectionDemo.class);
        //启动容器
        applicationContext.refresh();
        //查找AutowiredAnnotationInjectionDemo
        AutowiredAnnotationInjectionDemo demoBean = applicationContext.getBean(AutowiredAnnotationInjectionDemo.class);
        System.out.println("demoBean.wakingLeon: " + demoBean.wakingLeon);
        //手动销毁容器
        applicationContext.close();
    }

源码分析

首先,我们看@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.
	 * <p>Defaults to {@code true}.
	 */
	boolean required() default true;

}

先看一下AutowiredAnnotationBeanPostProcessor继承结构图(图画的有点丑,哈哈):

在这里插入图片描述
通过此图可得出一些基本结论:AutowiredAnnotationBeanPostProcessor分别实现了InstantiationAwareBeanPostProcessorAdapter(Bean实例化相关)、MergedBeanDefinitionPostProcessor(合并BeanDefinition)、
PriorityOrdered(排序), BeanFactoryAware(BeanFactory的回调)

AutowiredAnnotationBeanPostProcessor

第一阶段:元信息解析

首先, 通过构造方法:

/**
	 * Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
	 * standard {@link Autowired @Autowired} annotation.
	 * <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
	 * if available.
	 */
	@SuppressWarnings("unchecked")
	public AutowiredAnnotationBeanPostProcessor() {
		this.autowiredAnnotationTypes.add(Autowired.class);
		this.autowiredAnnotationTypes.add(Value.class);
		try {
			//Inject要生效需讲javax.inject.Inject加入classpath中
			this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
					ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
			logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
		}
		catch (ClassNotFoundException ex) {
			// JSR-330 API not available - simply skip.
		}
	}

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

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

	public void setAutowiredAnnotationTypes(Set<Class<? extends Annotation>> autowiredAnnotationTypes) {
		Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
		this.autowiredAnnotationTypes.clear();
		this.autowiredAnnotationTypes.addAll(autowiredAnnotationTypes);
	}
	
	
	/**
	* 从这里开始有三个依次在执行中调用的方法,是解析注解元信息非常重要的核心方法
	*/
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}



	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());
		// 这里用bean的名称作为key
		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) {
						metadata.clear(pvs);
					}
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

	//这里是核心,它的作用就是把所有@Autowired注解标注的依赖都转换为InjectionMetadata元信息给后面使用
	//
	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;
		
		//这里的do while 循环每个Class
		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
			
			//doWithLocalFields方法会递归的去找父类所有标注@Autowired的属性
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					//注: Autowired放在静态字段方法上,不会注入,但不会报错,会无效
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});
			//这里始终把父类放在第一位,所以父类是最先完成依赖注入的
			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return InjectionMetadata.forElements(elements, clazz);
	}


	

至此,通过postProcessMergedBeanDefinition()把我们注解标注的依赖及其父类的属性、方法进行合并Mergerd并全部转换成
InjectionMetadata,接下来进入注入阶段

第二阶段 注入

根据Bean的生命周期,Bean在实例化以后, 会调用AbstractAutowireCapableBeanFactory#populateBean()方法完成对Bean的属性填充,这个方法里面会触发postProcessPropertyValues()方法给属性赋值:

			//AbstractAutowireCapableBeanFactory#populateBean()里找到这个循环,它会取出容器中的所有BeanPostProcessor
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						//postProcessPropertyValues是一个模板方法
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}

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

	//postProcessProperties在所有setter方法之前执行
	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		//从缓存中取出对应已经解析好的元信息
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try {
			//这里就是依赖注入的核心,InjectionMetadata的inject
			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;
	}

	@Deprecated  //已过期
	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {

		return postProcessProperties(pvs, bean, beanName);
	}

终于找到了核心InjectionMetadata#inject(),那么我们找一个实现,AutowiredFieldElement

//继承静态抽象内部类InjectionMetadata.InjectedElement,且为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 {
			//InjectedElement 的member是反射里面的顶层接口,Field Method还有Constructor都是他的实现
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				//这里面会调用到beanFactory.resolveDependency
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			}
			else {
				//这里将field包装成DependencyDescriptor 
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				//设置containingClass
				desc.setContainingClass(bean.getClass());
				//从LinkedHashSet看出注入的是有顺序的,按BeanDefinition定义先后的顺序
				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try {
					//重点方法, beanFactory#resolveDependency 从beanFactory里面获取依赖值
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				}
				
				//这里把value缓存起来,当同一个Field多次注入时提高效率
				synchronized (this) {
					if (!this.cached) {
						if (value != null || this.required) {
							//缓存值为DependencyDescriptor对象
							this.cachedFieldValue = desc;
							registerDependentBeans(beanName, autowiredBeanNames);
							if (autowiredBeanNames.size() == 1) {
								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;
					}
				}
			}
			//最终通过反射, 将value赋值到feild
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}
	}

我们跟进这里的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 的每个描述字段可以大致猜到注入的wakingLeon依赖对应的相关描述
1: 实时注入(eager=true)并且是required=true
2:通过类型(WakingLeon.class)依赖查找
3: 字段名称 wakingLeon

在resolveDependency里面debug, 观察DependencyDescriptor 里的值和猜测的基本一致 :

在这里插入图片描述

回到resolveDependency方法:

	@Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		//支持Optional
		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 Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
		//这里会解析@Lazy注解,创建代理对象
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
			//绝大多数情况下都会执行doResolveDependency
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}




	@Nullable
	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
		//这个方法是通过依赖描述符处理注入多次嵌套
		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			...
			
			//这里判断是否是集合类型的多个bean,包括Array、 Collection、Map
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			//这里的beanName指的是被注入的bean的名称,本文中指的就是AutowiredAnnotationInjectionDemo,type指的就是注入的类(WakingLeon.class)
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			...
			return result;
		}
		finally {
			//设置到当前的注入点
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}
	

总结

Spring使用了大量的委托代理还有模板方法等,实现了高内聚低耦合的特点。整个对@Autowired依赖注入的流程分为两个周期,第一个是解析元信息并放入缓存中,第二个周期是注入,
在我看来,每个阶段有每个阶段的核心,解析元信息核心是模仿双亲委派的父类优先的原则去合并BeanDefition, 并全部转换成InjectionMetadata, 第二个阶段就是InjectionMetadata的inject方法的实现,其中会涉及到beanFactory.resolveDependency,这里可以处理多种注入类型的封装,包括Optional、ObjectFactory、ObjectProvider和jsr330 里面的依赖注入方案,最后处理默认注入操作,最终通过反射将值设置到字段当中。
理解了依赖注入的流程后,可以做个扩展。如果遇到一些必须提早注册一些Bean的场景的时候,就可以自定义依赖注入注解和AutowiredAnnotationBeanPostProcessor去提早触发注入机制,代码简单演示一下:

//注解是没法通过extends继承,可以将原注解标注在我们自定义注解上的方式继承
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Autowired
public @interface LeonAutowired {
}
**
 * 自定义注入演示类
 */
public class AutowiredAnnotationInjectionDemo  {

    @LeonAutowired
    private WakingLeon wakingLeon;

    @Bean
    public WakingLeon wakingLeon(){
        WakingLeon wakingLeon = new WakingLeon();
        wakingLeon.setId(1L);
        wakingLeon.setName("Leon");
        return wakingLeon;
    }

	//注意这里要设置成static,不然依赖注入会失效,因为这个AutowiredAnnotationBeanPostProcessor定义在当前demo类中,想要拿到自定义的AutowiredAnnotationBeanPostProcessor,就必须实例化demo类 
	//但是在实例化demo类LeonAutowired也同时被处理了,此时还没有自定义的AutowiredAnnotationBeanPostProcessor,因此不认识@LeonAutowired,
	//因此被注入了null。然后等实例化完了之后自定义的AutowiredAnnotationBeanPostProcessor才拿到
    @Bean(value = "LeonAutowiredAnnotationBeanPostProcessor")
    public static AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor(){
        AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        //这里可以把默认的注解放进来或者用@Order注解去实现优先级
        beanPostProcessor.setAutowiredAnnotationType(LeonAutowired.class);
        return beanPostProcessor;
    }

    public static void main(String[] args) {
        //新建一个容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //将当前被注入的类注册到容器中
        applicationContext.register(AutowiredAnnotationInjectionDemo.class);
        //启动容器
        applicationContext.refresh();
        //查找AutowiredAnnotationInjectionDemo
        AutowiredAnnotationInjectionDemo demoBean = applicationContext.getBean(AutowiredAnnotationInjectionDemo.class);
        System.out.println("demoBean.wakingLeon: " + demoBean.wakingLeon);
        //手动销毁容器
        applicationContext.close();
    }
}

执行一下:
在这里插入图片描述
这个Bean就通过自定义的@LeonAutowired注解注入进来了。
至此,@Autowired的依赖注入流程就分析完毕。与@Autowired等效的@Resource注解虽然注入效果一样,但是是通过另一个BeanPostProcessor–CommonAnnotationBeanPostProcessor去实现的,实现流程大同小异,提供对jdk注入注解和ejb WebServiceRef等注入注解的支持,这里就不再总结了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值