注解@Autowired如何自动装配

一、概念:@Autowired是spring框架2.5之后出现,用来简化在bean当中需要定义属性实现自动装配的注解,夜市最常见注解之一。

二、作用位置:可以修饰在方法,参数和注解等属性上(以下是源码)

//可以修饰的位置包括,   构造方法,        普通方法,           参数,       
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER,
   /* 字段,*/                      /* 注解 */
 ElementType.FIELD, ElementType.ANNOTATION_TYPE})
//保留策略是在运行时
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
//声明了依赖属性 默认是true
    boolean required() default true;
}

从我们看到的Autowired源码中是没有任何关于自动装配的代码的,完成自动装配的代码是在AutowiredAnnotationBeanPostProcessor类中。

注解@Autowired如何自动装配_第1张图片

<一>找到需要装配的元素并保存(解析Autowired)

1.进源码可以看见,AutowiredAnnotationBeanPostProcessor实现了
MergedBeanDefinitionPostProcessor接口,重写postProcessMergedBeanDefinition()方法,实现的注入类型的预解析。

//源码中的预加载方法
    
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
 Class beanType, String beanName) {
        InjectionMetadata metadata 
            = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);
        metadata.checkConfigMembers(beanDefinition);
    }

2.主要逻辑是在findAutowiringMetadata()方法。这个方法主要是找到需要自动装配的元素,该方法会去调用buildAutowiringMetadata()方法构建元数据信息。

  // findAutowiringMetadata源码
private InjectionMetadata findAutowiringMetadata(String beanName, Class clazz, @Nullable PropertyValues pvs) {
//缓存Bean的名称
        String cacheKey = StringUtils.hasLength(beanName) ? beanName : clazz.getName();
        InjectionMetadata metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
//判断缓存是否存在
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized(this.injectionMetadataCache) {
                metadata = (InjectionMetadata)this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }
//目标Bean的元数据信息
                    metadata = this.buildAutowiringMetadata(clazz);
//存入缓存
                    this.injectionMetadataCache.put(cacheKey, metadata);
                }
            }
        }

        return metadata;
    }

3.核心逻辑在buildAutowiringMetadata()方法中

private InjectionMetadata buildAutowiringMetadata(Class clazz) {
        LinkedList elements = new LinkedList();
        Class targetClass = clazz;

        do {
            LinkedList currElements = new LinkedList();
         //通过反射获取目标类中所有的字段,并遍历每一个字段,然后通过findAutowiredAnnotation()                    方法判断字段是否使用@Autowired和@Value修饰,
        // 如果字段被@Autowired和@Value修饰,则返回注解的相关属性信息

            ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
                AnnotationAttributes ann = this.findAutowiredAnnotation(field);
                if (ann != null) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (this.logger.isWarnEnabled()) {
                            this.logger.warn("Autowired annotation is not supported on static fields: " + field);
                        }

                        return;
                    }
                    // 获取到@Autowired注解的required()的值
                    boolean required = this.determineRequiredStatus(ann);
                    // 将该字段封成AutowiredFieldElement对象
                    currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
                }

            });
            //反射获取目标Bean的所有方法
            ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                    AnnotationAttributes ann = this.findAutowiredAnnotation(bridgedMethod);
                    if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                        if (Modifier.isStatic(method.getModifiers())) {
                            if (this.logger.isWarnEnabled()) {
                                this.logger.warn("Autowired annotation is not supported on static methods: " + method);
                            }

                            return;
                        }

                        if (method.getParameterCount() == 0 && this.logger.isWarnEnabled()) {
                            this.logger.warn("Autowired annotation should only be used on methods with parameters: " + method);
                        }

                        boolean required = this.determineRequiredStatus(ann);
                        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                        
                // 将该字段封成AutowiredMethodElement对象
                        currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement(method, required, pd));
                    }

                }
            });
            elements.addAll(0, currElements);
            targetClass = targetClass.getSuperclass();
        }

    // 循环处理父类需要自动装配的元素
 while(targetClass != null && targetClass != Object.class);

    // 将目标类对应的所有自动注入相关的元信息封装成InjectionMetadata,然后合并到Bean定义中
        return new InjectionMetadata(clazz, elements);
    }

buildAutowiringMetadata()方法的步骤:

1》通过反射获取目标类中所有的字段并进行遍历,然后通过findAutowiredAnnotation()方法判断字段是否使用@Autowired和@Value修饰,如果字段被@Autowired和@Value修饰,则返回注解的所有属性信息。

2》通过反射获取目标类中所有的方法;

3》解析到字段和方法的元信息保存到List elements集合中,字段对应的是AutowiredFieldElement类型,方法对应的则是AutowiredMethodElement类型。

4》将目标类对应的所有自动注入相关的元信息封装成InjectionMetadata类,返回
 

buildAutowiringMetadata()方法执行完成后,会将解析得到的自动注入相关信息保存到缓存injectionMetadataCache

4.postProcessMergedBeanDefinition()方法将需要注入的属性信息通过checkConfigMembers()

封装在了InjectionMetadata类中,包含了装配和内装配类的所有信息。

public class InjectionMetadata {
    private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
    private final Class targetClass;
    private final Collection injectedElements;
    @Nullable
    private volatile Set checkedElements;

    public InjectionMetadata(Class targetClass, Collection elements) {
        this.targetClass = targetClass;
        this.injectedElements = elements;
    }

    public void checkConfigMembers(RootBeanDefinition beanDefinition) {
        Set checkedElements = new LinkedHashSet(this.injectedElements.size());
        Iterator var3 = this.injectedElements.iterator();

        while(var3.hasNext()) {
            InjectionMetadata.InjectedElement element = (InjectionMetadata.InjectedElement)var3.next();
            Member member = element.getMember();
            if (!beanDefinition.isExternallyManagedConfigMember(member)) {
                beanDefinition.registerExternallyManagedConfigMember(member);
                checkedElements.add(element);
                if (logger.isDebugEnabled()) {
                    logger.debug("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
                }
            }
        }

        this.checkedElements = checkedElements;
    }

 <二>自动注入属性

AutowiredAnnotationBeanPostProcessor间接实现了InstantiationAwareBeanPostProcessor接口,所以会执行到postProcessProperties()方法实现自动注入属性。

*postProcessProperties()方法的处理流程:


        1.调用findAutowiringMetadata()方法,尝试从缓存injectionMetadataCache中获取对应的注入元信息,如果缓存不存在,将会执行buildAutowiringMetadata()获取;
        2.循环InjectionMetadata的injectedElements属性,全部调用InjectionMetadata.InjectedElement.injectbean, beanName, pvs方法,通过反射方式设置属性的值;

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection checkedElements = this.checkedElements;
    Collection elementsToIterate =
        (checkedElements != null ? checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        // 循环elementsToIterate, 调用InjectionMetadata.InjectedElement.inject方法,通过反射方式设置属性的值;
        for (InjectedElement element : elementsToIterate) {
            if (logger.isTraceEnabled()) {
                logger.trace("Processing injected element of bean '" + beanName + "': " + element);
            }
            element.inject(target, beanName, pvs);
        }
    }
}

总结:以上分了两部分去说,一是解析@Autowired方法,到反射获取目标类的属性和方法,到存入injectionMetadataCache中,关键是buildAutowiringMetadata()方法。二是自动注入属性,还是反射的方式,取injectionMetadataCache中元信息,injectbean, beanName, pvs方法是关键

你可能感兴趣的:(springIOC,springDI,java,spring,开发语言)