@Autowired注解自动注入的原理


@Autowired自动注入是由AutowiredAnnotationBeanPostProcessor实现的,这个类实现了MergedBeanDefinitionPostProcessor接口,进而实现了postProcessMergedBeanDefinition方法,@Autowired注解正是通过这个方法实现注入类型的预解析,将需要依赖注入的属性信息封装到InjectionMetadata类中,InjectionMetadata类中包含了哪些需要注入的元素及元素要注入到哪个目标类中,在Spring容器启动的过程中初始化单例bean的时候通过populateBean方法实现对属性的注入。

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        InjectionMetadata metadata = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);
        metadata.checkConfigMembers(beanDefinition);
    }
}

自动注入的核心方法buildAutowiringMetadata

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    List<InjectedElement> elements = new ArrayList();
    //需要处理的目标类
    Class targetClass = clazz;

    do {
        List<InjectedElement> currElements = new ArrayList();
        /*通过反射获取该类所有的字段,并遍历每一个字段,并通过方法findAutowiredAnnotation遍历每一个字段的所用注解,并如果用autowired修饰了,则返回auotowired相关属性*/
        ReflectionUtils.doWithLocalFields(targetClass, (field) -> {
            AnnotationAttributes ann = this.findAutowiredAnnotation(field);
            //校验autowired注解是否用在了static方法上
            if (ann != null) {
                if (Modifier.isStatic(field.getModifiers())) {
                    if (this.logger.isInfoEnabled()) {
                        this.logger.info("Autowired annotation is not supported on static fields: " + field);
                    }

                    return;
                }
                //判断是否指定了required
                boolean required = this.determineRequiredStatus(ann);
                currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
            }

        });
        //通过反射处理类的method
        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.isInfoEnabled()) {
                            this.logger.info("Autowired annotation is not supported on static methods: " + method);
                        }

                        return;
                    }

                    if (method.getParameterCount() == 0 && this.logger.isInfoEnabled()) {
                        this.logger.info("Autowired annotation should only be used on methods with parameters: " + method);
                    }
                    //用@Autowired修饰的注解可能不止一个,因此都加在currElements这个容器里面,一起处理
                    boolean required = this.determineRequiredStatus(ann);
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement(method, required, pd));
                }

            }
        });
        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    } while(targetClass != null && targetClass != Object.class);

    return new InjectionMetadata(clazz, elements);
}

最后返回一个InjectionMetadata类,这个类包含两部分,一部分是处理的目标类,一部分是通过反射获取到的集合

public class InjectionMetadata {
    public InjectionMetadata(Class<?> targetClass, Collection<InjectionMetadata.InjectedElement> elements) {
        this.targetClass = targetClass;
        this.injectedElements = elements;
    }
}

得到InjectionMetadata开始执行注入:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass(), pvs);

    try {
        metadata.inject(bean, beanName, pvs);
        return pvs;
    } catch (BeanCreationException var6) {
        throw var6;
    } catch (Throwable var7) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", var7);
    }
}

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectionMetadata.InjectedElement> checkedElements = this.checkedElements;
    Collection<InjectionMetadata.InjectedElement> elementsToIterate = checkedElements != null ? checkedElements : this.injectedElements;
    InjectionMetadata.InjectedElement element;
    if (!((Collection)elementsToIterate).isEmpty()) {
        for(Iterator var6 = ((Collection)elementsToIterate).iterator(); var6.hasNext(); element.inject(target, beanName, pvs)) {
            element = (InjectionMetadata.InjectedElement)var6.next();
            if (logger.isTraceEnabled()) {
                logger.trace("Processing injected element of bean '" + beanName + "': " + element);
            }
        }
    }

}

文章作者: Cody_
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Cody_ !
评论
 上一篇
Mybatis一个SQL的执行过程 Mybatis一个SQL的执行过程
Mybatis的所有语句的执行都是通过SqlSession对象来操作的,SqlSession是由SqlSessionFactory类生成的。首先根据配置文件来创建一个SqlSessionFactory,然后调用openSession来获取一
2021-01-24
下一篇 
Docker远程安全连接 Docker远程安全连接
配置Docker远程连接,我们可以配合Docker插件在本地打包就自动上传并创建容器,不用我们再去服务器中手动创建。网上的讲解大多都是直接开放一个端口就直接完事,这样自己玩玩可以,用于正式项目的话不出几个小时就会被扫描到进而被攻击,这次我们
2021-01-09
  目录