Spring IoC @Autowired 注解详解

前言

本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本。因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析。

我们平时使用 Spring 时,想要 依赖注入 时使用最多的是 @Autowired 注解了,本文主要讲解 Spring 是如何处理该注解并实现 依赖注入 的功能。

正文

首先我们看一个测试用例:

User 实体类:

Copy
public class User { private Long id; private String name; // 省略 get 和 set 方法 }

测试类:

Copy
public class AnnotationDependencyInjectTest { /** * @Autowired 字段注入 */ @Autowired private User user; private City city; /** * @Autowired 方法注入 */ @Autowired public void initCity(City city) { this.city = city; } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(AnnotationDependencyInjectTest.class); context.refresh(); AnnotationDependencyInjectTest bean = context.getBean(AnnotationDependencyInjectTest.class); // @Autowired 字段注入 System.out.println(bean.user); // @Autowired 方法注入 System.out.println(bean.city); UserHolder userHolder = context.getBean(UserHolder.class); // @Autowired 构造器注入 System.out.println(userHolder.getUser()); context.close(); } @Bean public User user() { User user = new User(); user.setId(1L); user.setName("leisurexi"); return user; } @Bean public City city() { City city = new City(); city.setId(1L); city.setName("北京"); return city; } /** * @Autowired 构造函数注入 */ static class UserHolder { private User user; @Autowired public UserHolder(User user) { this.user = user; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } }

上面分别展示了 @Autowired 注解的字段注入和方法注入,下面我们开始分析 Spring 是如何实现的。

首先使 @Autowired 注解生效的一个关键类是 AutowiredAnnotationBeanPostProcessor,该类实现了 InstantiationAwareBeanPostProcessorAdapter 抽象类;该抽象类就是一个适配器的作用提供了接口方法的默认实现,InstantiationAwareBeanPostProcessorAdapter 又实现了 SmartInstantiationAwareBeanPostProcessor 接口,同时实现该接口的 determineCandidateConstructors() 方法可以指定 bean 的候选构造函数;然后 SmartInstantiationAwareBeanPostProcessor 接口又继承了 InstantiationAwareBeanPostProcessor 接口,该接口提供了 bean 实例化前后的生命周期回调以及属性赋值前的后置处理方法,@Autowired 注解的属性注入就是通过重写该接口的 postProcessProperties() 实现的。这两个接口都在 Spring IoC bean 的创建 一文中有介绍过。下面我们看一下 AutowiredAnnotationBeanProcessor 的继承关系图:

关于 AutowiredAnnotationBeanPostProcessor 这个后置处理器是怎么加入到 beanFactory 中的,我们在 Spring IoC component-scan 节点详解 一文中介绍过主要是通过 AnnotationConfigUtils#registerAnnotationConfigProcessors() 实现的。

Copy
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) { // 省略其他代码... // 注册用于处理@Autowired、@Value、@Inject注解的后置处理器 if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // 省略其他代码... }

属性和方法注入#

AutowiredAnnotationBeanPostProcessor 中跟属性注入有关的方法有两个:postProcessMergedBeanDefinitionpostProcessPropertyValues

前者是 MergedBeanDefinitionPostProcessor 接口中的方法,定义如下:

Copy
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor { /** * 对指定bean的BeanDefinition合并后的处理方法回调 */ void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName); // 省略其他代码... }

后者是 InstantiationAwareBeanPostProcessor 接口中的方法,定义如下:

Copy
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { /** * Bean 实例化后属性赋值前调用,PropertyValues 是已经封装好的设置的属性值,返回 {@code null} 继续 * 使用现有属性,否则会替换 PropertyValues。 */ @Nullable default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { return null; } // 省略其他代码... }

关于这两个方法的调用时机,可以查看Spring IoC bean 的创建Spring IoC 属性赋值阶段

bean 合并后处理#

AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition#

首先执行的是 postProcessMergedBeanDefinition() 方法。

Copy
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { // 寻找需要注入的字段或方法,并封装成 InjectionMetadata,见下文详解 InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); // 检查元数据中的注解信息 metadata.checkConfigMembers(beanDefinition); }

InjectionMetadata 就是注入的元信息描述,主要字段如下:

Copy
public class InjectionMetadata { // 需要依赖注入的目标类 private final Class<?> targetClass; // 注入元素的集合 private final Collection<InjectedElement> injectedElements; // 忽略其它代码 }

InjectedElement 就是注入的元素,主要字段如下:

Copy
public abstract static class InjectedElement { // 注入的属性或方法 protected final Member member; // 需要注入的是否是字段 protected final boolean isField; }

查找需要注入的字段或方法#

AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata#

Copy
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // 首先从缓存中获取 InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); // 判断是否需要刷新,即metadata为null或者metadata中存储的targetClass和当前clazz不等 if (InjectionMetadata.needsRefresh(metadata, clazz)) { // 这里相当于是一个double check,防止多线程出现的并发问题 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; }

创建需要注入的元信息#

AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata#

Copy
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } // 判断当前类或其字段或其方法是否标注了autowiredAnnotationTypes中的注解,没有的话直接返回空的 List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); // 遍历targetClass中的字段 ReflectionUtils.doWithLocalFields(targetClass, field -> { // 获取field上的@Autowired注解信息 MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != null) { // 如果字段是静态类型是不会进行注入的 if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return; } // 获取@Autowired注解中的required属性 boolean required = determineRequiredStatus(ann); // 将装成AutowiredFieldElement添加进currElements currElements.add(new AutowiredFieldElement(field, required)); } }); // 遍历targetClass中的方法 ReflectionUtils.doWithLocalMethods(targetClass, method -> { // 找到桥接方法 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); // 判断方法的可见性,如果不可见则直接返回 if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } // 获取method上的@Autowired注解信息 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); } } // 获取@Autowired注解中的required属性 boolean required = determineRequiredStatus(ann); // 将方法和目标类型封装成属性描述符 PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); // 封装成AutowiredMethodElement添加进currElements currElements.add(new AutowiredMethodElement(method, required, pd)); } }); // 将currElements整个添加进elements elements.addAll(0, currElements); // 获取targetClass的父类,进行下一次循环 targetClass = targetClass.getSuperclass(); } // 当targetClass为空或者targetClass等于Object.class时会退出循环 while (targetClass != null && targetClass != Object.class); // 将elements和clazz封装成InjectionMetadata返回 return InjectionMetadata.forElements(elements, clazz); }

上面代码中的 findAutowiredAnnotation() 就是在遍历 autowiredAnnotationTypes 属性,看字段或者方法上的注解是否存在于 autowiredAnnotationTypes 中,或者其派生注解,找到第一个就返回,不会再继续遍历了。

Copy
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4); public AutowiredAnnotationBeanPostProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); this.autowiredAnnotationTypes.add(Value.class); try { 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 以及 @Inject (在 JSR-330 的jar包存在于当前环境时)。

至此,使用 @Autowired 修饰的字段和方法已经封装成 InjectionMetadata 并放在 injectionMetadataCache 缓存中,便于后续使用。

bean 属性的后置处理#

AutowireAnnotationBeanPostProcessor#postProcessProperties#

postProcessMergedBeanDefinition() 调用后 bean 就会进行实例化接着调用 postProcessProperties()

Copy
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 获取缓存中的 InjectionMetadata InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { // 进行属性的注入 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; } // InjectMetadata.java public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 获取检查后的元素 Collection<InjectedElement> checkedElements = this.checkedElements; // 如果checkedElements不为空就使用checkedElements,否则使用injectedElements Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { // 遍历elementsToIterate for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } // AutowiredFieldElement、AutowiredMethodElement这两个类继InjectionMetadata.InjectedElement // 各自重写了inject方法 element.inject(target, beanName, pvs); } } }

字段注入#

AutowiredFieldElement#inject#

Copy
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 强转成Field类型 Field field = (Field) this.member; Object value; if (this.cached) { // 如果缓存过,直接使用缓存的值,一般第一次注入都是false value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { // 构建依赖描述符 DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); // 获取类型转换器 TypeConverter typeConverter = beanFactory.getTypeConverter(); try { // 进行依赖解决,获取符合条件的bean value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } // 加锁 synchronized (this) { // 如果没有被缓存 if (!this.cached) { // 找到了需要的bean || 该字段是必要的 if (value != null || this.required) { // 将依赖描述符赋值给cachedFieldValue this.cachedFieldValue = desc; // 注册bean的依赖关系,用于检测是否循环依赖 registerDependentBeans(beanName, autowiredBeanNames); // 如果符合条件的bean只有一个 if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); // beanFactory含有名为autowiredBeanName的bean && 类型是匹配的 if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { // 将该属性解析到的bean的信息封装成ShortcutDependencyDescriptor // 之后可以通过调用resolveShortcut()来间接调beanFactory.getBean()快速获取bean this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } // 缓存标识设置为true this.cached = true; } } } // 如果找到了符合的bean,设置字段可访问,利用反射设置值 if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } }

上面代码中的 beanFactory.resolveDependency()Spring IoC bean 的创建 一文中有介绍过,这里不再赘述;同样 registerDependentBeans() 最终会调用 DefaultSingletonBeanRegistry.registerDependentBean() ,该方法在 Spring IoC bean 的创建 一文中有介绍过,这里也不再赘述。

方法注入#

AutowiredMethodElement#inject#

Copy
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 检查是否需要跳过 if (checkPropertySkipping(pvs)) { return; } // 强转成Method类型 Method method = (Method) this.member; Object[] arguments; if (this.cached) { // 如果缓存过,直接调用beanFactory.resolveDependency()返回符合的bean arguments = resolveCachedArguments(beanName); } else { // 获取参数数量 int argumentCount = method.getParameterCount(); arguments = new Object[argumentCount]; // 创建依赖描述符数组 DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount]; // 记录用于自动注入bean的名称集合 Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount); Assert.state(beanFactory != null, "No BeanFactory available"); // 获取类型转换器 TypeConverter typeConverter = beanFactory.getTypeConverter(); // 遍历参数 for (int i = 0; i < arguments.length; i++) { // 将方法和参数的下标构建成MethodParameter,这里面主要记录了参数的下标和类型 MethodParameter methodParam = new MethodParameter(method, i); // 将MethodParameter构建成DependencyDescriptor DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required); currDesc.setContainingClass(bean.getClass()); descriptors[i] = currDesc; try { // 进行依赖解决,找到符合条件的bean Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter); if (arg == null && !this.required) { arguments = null; break; } arguments[i] = arg; } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex); } } // 这里跟字段注入差不多,就是注册bean的依赖关系,并且缓存每个参数的ShortcutDependencyDescriptor synchronized (this) { if (!this.cached) { if (arguments != null) { DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length); registerDependentBeans(beanName, autowiredBeans); if (autowiredBeans.size() == argumentCount) { Iterator<String> it = autowiredBeans.iterator(); Class<?>[] paramTypes = method.getParameterTypes(); for (int i = 0; i < paramTypes.length; i++) { String autowiredBeanName = it.next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) { cachedMethodArguments[i] = new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName, paramTypes[i]); } } } this.cachedMethodArguments = cachedMethodArguments; } else { this.cachedMethodArguments = null; } this.cached = true; } } } // 找到了符合条件的bean if (arguments != null) { try { // 设置方法可访问,利用反射进行方法调用,传入参数 ReflectionUtils.makeAccessible(method); method.invoke(bean, arguments); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }

构造器注入#

构造器注入就是通过调用 determineCandidateConstructors() 来返回合适的构造器。

Copy
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeanCreationException { // Quick check on the concurrent map first, with minimal locking. // 首先从缓存中获取 Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass); // 缓存为空 if (candidateConstructors == null) { // Fully synchronized resolution now... // 这里相当于double check synchronized (this.candidateConstructorsCache) { candidateConstructors = this.candidateConstructorsCache.get(beanClass); if (candidateConstructors == null) { Constructor<?>[] rawCandidates; try { // 获取beanClass的所有构造函数 rawCandidates = beanClass.getDeclaredConstructors(); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() +"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); } // 存放标注了@Autowired注解的构造器 List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length); // 存放标注了@Autowired注解,并且required为true的构造器 Constructor<?> requiredConstructor = null; Constructor<?> defaultConstructor = null; for (Constructor<?> candidate : rawCandidates) { // 获取构造器上的@Autowired注解信息 MergedAnnotation<?> ann = findAutowiredAnnotation(candidate); if (ann == null) { // 如果没有从候选者找到注解,则尝试解析beanClass的原始类(针对CGLIB代理) Class<?> userClass = ClassUtils.getUserClass(beanClass); if (userClass != beanClass) { try { Constructor<?> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes()); ann = findAutowiredAnnotation(superCtor); } catch (NoSuchMethodException ex) { // Simply proceed, no equivalent superclass constructor found... } } } if (ann != null) { // 如果requiredConstructor不为空,代表有多个标注了@Autowired且required为true的构造器,此时Spring不知道选择哪个抛出异常 if (requiredConstructor != null) { throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: " + candidate +". Found constructor with 'required' Autowired annotation already: " + requiredConstructor); } // 获取@Autowired注解的reuired属性的值 boolean required = determineRequiredStatus(ann); if (required) { // 如果当前候选者是@Autowired(required = true),则之前不能存在其他使用@Autowire注解的构造函数,否则抛异常 if (!candidates.isEmpty()) { throw new BeanCreationException(beanName,"Invalid autowire-marked constructors: " + candidates +". Found constructor with 'required' Autowired annotation: " + candidate); } // required为true将当前构造器赋值给requiredConstructor requiredConstructor = candidate; } // 将当前构造器加入进候选构造器中 candidates.add(candidate); } // 没有标注了@Autowired注解且参数长度为0,赋值为默认构造器 else if (candidate.getParameterCount() == 0) { defaultConstructor = candidate; } } // 有标注了@Autowired注解的构造器 if (!candidates.isEmpty()) { // Add default constructor to list of optional constructors, as fallback. // 没有标注了@Autowired且required为true的构造器 if (requiredConstructor == null) { // 默认构造器不为空 if (defaultConstructor != null) { // 将默认构造器加入进候选构造器中 candidates.add(defaultConstructor); } } // 将候选者赋值给candidateConstructors candidateConstructors = candidates.toArray(new Constructor<?>[0]); } // 只有1个构造器 && 参数长度大于0(非默认构造器),只能用它当做候选者了 else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) { candidateConstructors = new Constructor<?>[] {rawCandidates[0]}; } // 只有1个构造器 && 参数长度大于0,只能用它当做候选者了 else if (nonSyntheticConstructors == 2 && primaryConstructor != null && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) { candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor}; } else if (nonSyntheticConstructors == 1 && primaryConstructor != null) { candidateConstructors = new Constructor<?>[] {primaryConstructor}; } // 返回一个空的Constructor else { candidateConstructors = new Constructor<?>[0]; } // 缓存候选的构造器 this.candidateConstructorsCache.put(beanClass, candidateConstructors); } } } // 如果候选构造器长度大于0,直接返回,否则返回null return (candidateConstructors.length > 0 ? candidateConstructors : null); }

关于 SmartInstantiationAwareBeanPostProcessor 接口的调用时机,在 Spring IoC bean 的创建 一文中有介绍过,这里就不再赘述了。

总结

本文主要介绍了 Spring 对 @Autowired 注解的主要处理过程,结合前面的 Spring IoC bean 的加载Spring IoC bean 的创建 以及 Spring IoC 属性赋值阶段 一起看才能更好的理解。

最后,我模仿 Spring 写了一个精简版,代码会持续更新。地址:https://github.com/leisurexi/tiny-spring

posted @   leisurexi  阅读(3008)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示
CONTENTS