Spring源码 - @Autowired原理分析(AutowiredAnnotationBeanPostProcessor)

目录

1、MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

2、#determineCandidateConstructors

3、InstantiationAwareBeanPostProcessor#postProcessProperties


    分析完CommonAnnotationBeanPostProcessor之后,再来看AutowiredAnnotationBeanPostProcessor的实现就简单一些了。由于不用解析@PostConstruct、@PreDestroy注解,所以去除了父类InitDestroyAnnotationBeanPostProcessor的逻辑;BeanPostProcess的postProcessBeforeInitialization中也不用进行处理了,返回原对象。但是@Autowired注解不仅能修饰字段,还能修改构造函数,所以继承了父类InstantiationAwareBeanPostProcessorAdapter。

    还是先看看其无参数中,添加的解析的类型(说明能解析@Autowired和@Value):

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的结构层级:

    后面就还是按照BeanPostProcess的调用过程进行分析:

 

1、MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

    同样的该接口的回调时机为:SpringIoc源码(十七)- BeanFactory(六)- getBean(doCreateBean总览)#3、MergedBeanDefinitionPostProcessor回调,在对BeanDefinition进行merge之后,允许修改其值。由于CommonAnnotationBeanPostProcessor中需要处理父类的注解,二而当前只需要处理本类中的注解,如下:

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
    Class<?> beanType, String beanName) {

    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

    对于InjectionMetadata的checkConfigMembers可以参见上一篇博客,那么主要的是怎么将标记有@Autowired注解的信息加载为该对象,findAutowiringMetadata方法入下:

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());
    // Quick check on the concurrent map first, with minimal locking.
    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;
}

     大体结构如@Resource注解,主要在buildAutowiringMetadata中:

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 {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            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;
                }
                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())) {
                    return;
                }
                if (method.getParameterCount() == 0) {
                }
                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);
}

    根据当前的类,递归父类一直到Object类,判断方法即字段上是否有@Autowired注解,如果有则进行解析并往容器中添加AutowiredFieldElement或者AutowiredMethodElement对象。其中主要的方法为findAutowiredAnnotation

@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
    MergedAnnotations annotations = MergedAnnotations.from(ao);
    for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
        MergedAnnotation<?> annotation = annotations.get(type);
        if (annotation.isPresent()) {
            return annotation;
        }
    }
    return null;
}

    方法名称虽然看上去值解析@Autowired注解,但是构造中还加入了@Value。所以这里也进行了解析。递归完成后则将所有本类和父类中,@Autowired和@Value修饰的字段和方法都以AutowiredFieldElement或者AutowiredMethodElement的类型加入容器中。

 

2、#determineCandidateConstructors

    由于@Autowired可以修改构造函数,那么在getBean的创建Bean,通过构造函数反射创建对象时。determineConstructorsFromBeanPostProcessors允许调用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法。而当前调用了适配器模式模式InstantiationAwareBeanPostProcessorAdapterdetermineCandidateConstructors方法。调用时机可以参见SpringIoc源码(十八)- BeanFactory(七)- getBean(doCreateBean - createBeanInstance实例创建)

@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
        throws BeanCreationException {

    // Let's check for lookup methods here..
    if (!this.lookupMethodsChecked.contains(beanName)) {
        try {
            ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
                @Override
                public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                    Lookup lookup = method.getAnnotation(Lookup.class);
                    if (lookup != null) {
                        LookupOverride override = new LookupOverride(method, lookup.value());
                        try {
                            RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
                            mbd.getMethodOverrides().addOverride(override);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(beanName, "省略");
                        }
                    }
                }
            });
        }
        catch (IllegalStateException ex) {
            throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
        }
        catch (NoClassDefFoundError err) {
            throw new BeanCreationException(beanName, "省略", err);
        }
        this.lookupMethodsChecked.add(beanName);
    }

    // Quick check on the concurrent map first, with minimal locking.
    Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    if (candidateConstructors == null) {
        // Fully synchronized resolution now...
        synchronized (this.candidateConstructorsCache) {
            candidateConstructors = this.candidateConstructorsCache.get(beanClass);
            if (candidateConstructors == null) {
                Constructor<?>[] rawCandidates;
                try {
                    rawCandidates = beanClass.getDeclaredConstructors();
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "省略", ex);
                }
                List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
                Constructor<?> requiredConstructor = null;
                Constructor<?> defaultConstructor = null;
                for (Constructor<?> candidate : rawCandidates) {
                    AnnotationAttributes ann = findAutowiredAnnotation(candidate);
                    if (ann == null) {
                        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) {
                        if (requiredConstructor != null) {
                            throw new BeanCreationException(beanName,"省略");
                        }
                        boolean required = determineRequiredStatus(ann);
                        if (required) {
                            if (!candidates.isEmpty()) {
                                throw new BeanCreationException(beanName, "省略");
                            }
                            requiredConstructor = candidate;
                        }
                        candidates.add(candidate);
                    }
                    else if (candidate.getParameterTypes().length == 0) {
                        defaultConstructor = candidate;
                    }
                }
                if (!candidates.isEmpty()) {
                    // Add default constructor to list of optional constructors, as fallback.
                    if (requiredConstructor == null) {
                        if (defaultConstructor != null) {
                            candidates.add(defaultConstructor);
                        }
                        else if (candidates.size() == 1 && logger.isWarnEnabled()) {
                            // 省略日志
                        }
                    }
                    candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
                }
                else if (rawCandidates.length == 1 && rawCandidates[0].getParameterTypes().length > 0) {
                    candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
                }
                else {
                    candidateConstructors = new Constructor<?>[0];
                }
                this.candidateConstructorsCache.put(beanClass, candidateConstructors);
            }
        }
    }
    return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

    

3、InstantiationAwareBeanPostProcessor#postProcessProperties

    调用时机为:SpringIoc源码(十九)- BeanFactory(八)- getBean(doCreateBean - populateBean属性填充)#3、InstantiationAwareBeanPostProcessor#postProcessPropertyValues属性填充

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    // 省略异常处理代码
    metadata.inject(bean, beanName, pvs);
    return pvs;
}

    findAutowiringMetadata方法的过程上面分析过了(并且第一次处理完就有数据了),调用inject方法可以查看上一篇博客。这样整个@Autowired、@Value注解的解析过程就清楚了。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值