spring中BeanPostProcessor之四:AutowiredAnnotationBeanPostProcessor01 spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor01

在《spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)》中分析了CommonAnnotationBeanPostProcessor类中的postProcessMergedBeanDefinition方法的作用,即是对类中的@Resources、@WebServiceRef、@EJB三个注解进行解析并缓存起来,以便后续执行postProcessProperties方法的时候用到缓存的信息。在spring启动过程中还有一个和CommonAnnotationBeanPostProcessor类相似的bean后置处理器,该类就是AutowiredAnnotationBeanPostProcessor,该bean后置处理器的作用是处理@Autowired、@Value、@Inject注解。

一、概述

前面说到AutowiredAnnotationBeanPostProcessor类是解析@Autowired注解的,那么该注解的作用是什么那,是怎么定义的那

@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;

}

上面是该注解的定义,该注解的作用是自动注入,该注解是Spring提供的注解(@Resource、@WebServiceRef、@EJB均是java提供的)。

AutowriedAnnotationBeanPostProcessor要解析@Autowired注解那么按照前面分析的CommonAnnotationBeanPostProcessor和InitDestroyBeanPostProcessor两个类,必须要先有要解析的类型,也就是初始化解析的类型,看AutoworedAnnotationBeanPostProcessor的构造方法,

@SuppressWarnings("unchecked")
    public AutowiredAnnotationBeanPostProcessor() {
        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.try {
            this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                    ClassUtils.forName("javax.inject.Inject",AutowiredAnnotationBeanPostProcessor..getClassLoader()));
            logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
        }
        catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }

上面是其默认的构造方法,可以看到向autowiredAnnotationTypes中加了三个注解:@Autowired、@Value、@Inject,其中@Inject是java中的注解,其余两个均是Spring提供的注解。那么这里其实是说明AutowiredAnnotationBeanPostProcessor类是解析这三个注解的,我们继续往下分析。

二、详述

 1、方法概述

下面看AutoWiredAnnotationBeanPostProcessor类中的方法,

上面给出了AutoWiredAnnotationBeanPostProcessor类中的主要的方法,重点看postProcessMergedBeanDefinition和postProcessProperties方法,postProcessPropertyValue方法在前边已经说过该方法已经废弃了,调用的是postProcessProperties方法。

2、postProcessMergedBeanDefinition

该方法的作用是解析类中标记了@AutoWired、@Value、@Inject注解的属性和方法,下面看具体的方法定义,

@Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,Class<?> beanType,String beanName) {
        InjectionMetadata metadata = findAutowiringMetadata(beanName,beanType,null);
        metadata.checkConfigMembers(beanDefinition);
    }

2.1、findAutowiringMetadata

下面看findAutowiringMetadata方法

private InjectionMetadata findAutowiringMetadata(String beanName,1)"> 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.
//从缓存中获得该类的信息
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
//判断是否需要刷新缓存
if (InjectionMetadata.needsRefresh(metadata,clazz)) { synchronized (.injectionMetadataCache) { metadata = .injectionMetadataCache.get(cacheKey); if (metadata != ) { metadata.clear(pvs); }
//查找目标类clazz中的标识了@AutoWired、@Value、@Inejct注解 metadata
= buildAutowiringMetadata(clazz); .injectionMetadataCache.put(cacheKey,metadata); } } } return metadata; }

从上面的代码中可以看出最终是把标识了@AutoWired、@Value、@Inject注解的方法或字段信息封装为Metadata然后放在了injectionMetadataCache中,重点看buildAutowiringMetadata方法,

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
        autowiredAnnotationTypes中得值为
         * @AutoWired org.springframework.beans.factory.annotation.Autowired
         * @Value org.springframework.beans.factory.annotation.Value
         * @Inject javax.inject.Inject
         * 
         */
        
        if (!AnnotationUtils.isCandidateClass(clazz,1)">.autowiredAnnotationTypes)) {
             InjectionMetadata.EMPTY;
        }

        List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
        Class<?> targetClass = clazz;

        dofinal List<InjectionMetadata.InjectedElement> currElements = ();

            判断字段上是否存在autowiredAnnotationTypes中的注解
            ReflectionUtils.doWithLocalFields(targetClass,field -> {
                MergedAnnotation<?> ann = findAutowiredAnnotation(field);
                if (ann != ) {
                     (Modifier.isStatic(field.getModifiers())) {
                         (logger.isInfoEnabled()) {
                            logger.info("Autowired annotation is not supported on static fields: " + field);
                        }
                        ;
                    }
                    boolean required = determineRequiredStatus(ann);
                    currElements.add(new AutowiredFieldElement(field,required));
                }
            });

            判断方法上是否存在autowiredAnnotationTypes中的注解
            ReflectionUtils.doWithLocalMethods(targetClass,method -> {
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method,bridgedMethod)) {
                    ;
                }
                MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
                null && method.equals(ClassUtils.getMostSpecificMethod(method,clazz))) {
                     (Modifier.isStatic(method.getModifiers())) {
                         (logger.isInfoEnabled()) {
                            logger.info("Autowired annotation is not supported on static methods: " + method);
                        }
                        if (method.getParameterCount() == 0) {
                         (logger.isInfoEnabled()) {
                            logger.info("Autowired annotation should only be used on methods with parameters: " +
                                    method);
                        }
                    }
                     determineRequiredStatus(ann);
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod,clazz);
                    currElements.add( AutowiredMethodElement(method,required,pd));
                }
            });

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

         InjectionMetadata.forElements(elements,clazz);
    }

该代码比较多,主要是对目标类中的方法和字段信息进行了检查,判断是否标注了@AutoWired、@Value、@Inject三个注解,最后返回InjectionMetadata.forElements该方法是做什么的那,由于前边生成的对象是elements的对象,看elements对象的类型,

List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();

是一个ArrayList类型,泛型是InjectionMetadata.InejctedElement,下面看该方法,

static InjectionMetadata forElements(Collection<InjectedElement> elements,1)">return (elements.isEmpty() ? InjectionMetadata.EMPTY :  InjectionMetadata(clazz,elements));
    }

从上面的代码可以看到,最终是new了一个InjectionMetadata的实例。最终buildAutowiringMetadata方法返回的是一个InjectionMetadata的实例。

buildAutowiringMetadata方法执行完以后,在findAutowiringMetadata方法中,把返回的InjectionMetadata实例放入了injectionMetadataCache中,最终返回一个InjectionMetadata实例。

2.2、checkConfigMembers

在postProcessMergedBeanDefinition方法中的第二行代码即调用了checkConfigMembers方法

metadata.checkConfigMembers(beanDefinition);

该方法的定义如下,

void checkConfigMembers(RootBeanDefinition beanDefinition) {
        Set<InjectedElement> checkedElements = new LinkedHashSet<>(.injectedElements.size());
        for (InjectedElement element : .injectedElements) {
            Member member = element.getMember();
            beanDefinition.isExternallyManagedConfigMember(member)) {
                beanDefinition.registerExternallyManagedConfigMember(member);
                checkedElements.add(element);
                 (logger.isTraceEnabled()) {
                    logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
                }
            }
        }
        this.checkedElements = checkedElements;
    }

从上面的代码中可以看出首先new了一个checkedElements,使用的是injectedElements的长度,injectedElements是什么那,怎么赋值的那。在buildAutowiringMetadata方法的最后调用了InectionMetadata.forElements方法,在该方法中最后生成了一个InjectionMetadata对象,传入了elements对象,便是该对象。

checkConfiMembers方法主要是调用了beanDefintion.isExternallyManagedConfigMemgber方法,该方法暂时不讨论。

 

3、postProcessProperties

上面分析了postProcessMergedBeanDefinition方法后,我们知道该方法的作用就是收集类中的标注了@AutoWired、@Value、@Inject注解的字段或方法,那么postProcessProperties方法便是在进行赋值的时候调用的,

完成@AutoWired属性的注入
    @Override
     PropertyValues postProcessProperties(PropertyValues pvs,Object bean,String beanName) {
        再次获取了类中标注了@AutoWired、@Value、@Inject属性的信息
        InjectionMetadata metadata = findAutowiringMetadata(beanName,bean.getClass(),pvs);
        属性注入
            metadata.inject(bean,beanName,pvs);
        }
         (BeanCreationException ex) {
            throw ex;
        }
         (Throwable ex) {
            throw new BeanCreationException(beanName,"Injection of autowired dependencies failed" pvs;
    }

在该方法中又一次获取了类中标注了@AutoWired、@Value、@Inject属性的信息,重点是下面这行代码,

属性注入
            metadata.inject(bean,pvs);

下面看inject方法,

void inject(Object target,@Nullable String beanName,@Nullable PropertyValues pvs) throws Throwable {
        Collection<InjectedElement> checkedElements = .checkedElements;
        如果checkedElements为空,则取injectedElements
        Collection<InjectedElement> elementsToIterate =
                (checkedElements != null ? checkedElements : .injectedElements);
        elementsToIterate.isEmpty()) {
            for (InjectedElement element : elementsToIterate) {
                 (logger.isTraceEnabled()) {
                    logger.trace("Processing injected element of bean '" + beanName + "': " + element);
                }
                进行属性注入
                element.inject(target,pvs);
            }
        }
    }

上面在进行属性注入的时候调用了element.inject方法,该方法在InjectionMetadata.InjectedElement类中,进去该方法看到如下,


         * Either this or {@link #getResourceToInject} needs to be overridden.
         */
        protected  inject(Object target,@Nullable String requestingBeanName,@Nullable PropertyValues pvs)
                 Throwable {

            if (.isField) {
                Field field = (Field) .member;
                ReflectionUtils.makeAccessible(field);
                field.set(target,getResourceToInject(target,requestingBeanName));
            }
            else {
                 (checkPropertySkipping(pvs)) {
                    ;
                }
                 {
                    Method method = (Method) .member;
                    ReflectionUtils.makeAccessible(method);
                    method.invoke(target,requestingBeanName));
                }
                 (InvocationTargetException ex) {
                     ex.getTargetException();
                }
            }
        }

看这方法的注释,意思是需要覆盖该方法,也就是说这里调用的不是上面的inject方法,在回到下面的代码

再来看AutowiredFieldElement是什么,

AutowiredFieldElement是AutowiredAnnotationBeanPostProcessor中的内部类,继承了InjectionMetadata.InjectedElement类,上面提到了该方法,那么该类中肯定覆盖了inject方法

@Override
        void inject(Object bean,1)"> Throwable {
            Field field = (Field) .member;
            Object value;
            .cached) {
                value = resolvedCachedArgument(beanName,1)">.cachedFieldValue);
            }
             {
                DependencyDescriptor desc = new DependencyDescriptor(field,1)">.required);
                desc.setContainingClass(bean.getClass());
                Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
                Assert.state(beanFactory != null,"No BeanFactory available");
                TypeConverter typeConverter = beanFactory.getTypeConverter();
                 {
                    value = beanFactory.resolveDependency(desc,autowiredBeanNames,typeConverter);
                }
                 (BeansException ex) {
                    new UnsatisfiedDependencyException( InjectionPoint(field),ex);
                }
                .cached) {
                        if (value != null || .required) {
                            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 =  ShortcutDependencyDescriptor(
                                            desc,autowiredBeanName,field.getType());
                                }
                            }
                        }
                         {
                            ;
                        }
                        this.cached = ;
                    }
                }
            }
            ) {
                ReflectionUtils.makeAccessible(field);
                field.set(bean,value);
            }
        }
    }

此方法的具体执行逻辑暂时不说。

三、使用场景

上面大体分析了AutowiredAnnotationBeanPostProcessor类中的postProcessMergedBeanDefinition和postProcessProperties两个方法,了解了其作用及执行时机,文中遗留的问题后面会继续分析。

 

有不当之处,欢迎指正,感谢!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原理介绍,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。传统事务中回滚点的使...
今天小编给大家分享的是一文解析spring中事务的传播机制,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获...
这篇文章主要介绍了SpringCloudAlibaba和SpringCloud有什么区别,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。Spring Cloud Netfli...
本篇文章和大家了解一下SpringCloud整合XXL-Job的几个步骤。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。第一步:整合pom文件,在S...
本篇文章和大家了解一下Spring延迟初始化会遇到什么问题。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。List 坑列表 = new ArrayList(2);...
这篇文章主要介绍了怎么使用Spring提供的不同缓存注解实现缓存的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇...
本篇内容主要讲解“Spring中的@Autowired和@Resource注解怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学...
今天小编给大家分享一下SpringSecurity怎么定义多个过滤器链的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家
这篇文章主要介绍“Spring的@Conditional注解怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring的@Con...
这篇文章主要介绍了SpringCloudGateway的熔断限流怎么配置的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringCloud&nb...
今天小编给大家分享一下怎么使用Spring解决循环依赖问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考
这篇文章主要介绍“Spring事务及传播机制的原理及应用方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Sp...
这篇“SpringCloudAlibaba框架实例应用分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价
本篇内容主要讲解“SpringBoot中怎么使用SpringMVC”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习...
这篇文章主要介绍“SpringMVC适配器模式作用范围是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringMVC
这篇“导入SpringCloud依赖失败如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要讲解了“SpringMVC核心DispatcherServlet处理流程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来
今天小编给大家分享一下SpringMVCHttpMessageConverter消息转换器怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以...
这篇文章主要介绍“Spring框架实现依赖注入的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring框架...
本篇内容介绍了“Spring单元测试控制Bean注入的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下