注解工作原理源码解析

本文引自我的个人博客: sunmingshuai.coding.me

spring框架提供的注解方式的注入 大大方便了程序员的编程 但从另外一个方面来看 spring把功能细节隐藏的更深了 对技术有点追求的人 一定会很好奇spring注解的工作的方式 这篇博客以讲解@Value``@Autowired``@Qualifier注解为例来讲解注解是怎么工作的 (其他注解如@Resource @Required注解的工作原理类似)
component-scan做了些什么:源码解读这篇博客的最后有介绍到 注册了一些注解处理器BPP 我们再看下这个方法

    public static Set registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {

        Set beanDefs = new LinkedHashSet(4);

        // @Configuration
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        //@Autowired @Value
        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));
        }

        //@Required
        if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        //@PostConsruct @Resouce 等java注解
        // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        //
        // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition();
            try {
                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                        AnnotationConfigUtils.class.getClassLoader()));
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        return beanDefs;
    }

注解以及对应的后置处理器如下表所示

注解 BPP
@Configuration ConfigurationClassPostProcessor
@Autowired(@Qualifier),@Value,@Inject AutowiredAnnotationBeanPostProcessor
@Required RequiredAnnotationBeanPostProcessor
@Postconstruct,PreDestroy,@Resource CommonAnnotationBeanPostProcessor
@Persistence PersistenceAnnotationBeanPostProcessor

我们看下AutowiredAnnotationBeanPostProcessor这个处理器 @Autowired``@Qualifier``@Value注解的解析就是在postProcessMergedBeanDefinition以及postProcessPropertyValues这两个方法中完成的

postProcessMergedBeanDefinition这个方法执行时间的节点是在创建bean的实例后 在populateBean()方法调用前调用的
这个方法主要完成的功能就是找出带有特定注解的field method 并记录在数据结构中

    // 执行的时间节点是bean刚刚初始化完 但在属性填充之前
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) {
        if (beanType != null) {
            //找出所有的字段或者方法上的@Autowired @Value @Inject注解 并保存
            InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
            //加入到BeanDefinition
            metadata.checkConfigMembers(beanDefinition);
        }
    }

最后会调用buildAutowiringMetadata(clazz)完成检查

    /**
     * 分别对field method做检查 是否存在相应注解
     *
     * @param clazz
     * @return
     */
    private InjectionMetadata buildAutowiringMetadata(Class clazz) {
        LinkedList elements = new LinkedList();
        Class targetClass = clazz;

        do {
            LinkedList currElements = new LinkedList();
            // 循环所有的field
            for (Field field : targetClass.getDeclaredFields()) {
                // 寻找@Autowired @Value @Inject注解 只处理一个
                Annotation ann = findAutowiredAnnotation(field);
                if (ann != null) {
                    //忽略静态属性的注入
                    if (Modifier.isStatic(field.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static fields: " + field);
                        }
                        continue;
                    }
                    boolean required = determineRequiredStatus(ann);
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            }
            // 循环所有的方法 比如setxxx方法注入
            for (Method method : targetClass.getDeclaredMethods()) {
                Annotation ann = null;
                Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                if (BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                    ann = findAutowiredAnnotation(bridgedMethod);
                }
                if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation is not supported on static methods: " + method);
                        }
                        continue;
                    }
                    if (method.getParameterTypes().length == 0) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Autowired annotation should be used on methods with actual parameters: " + method);
                        }
                    }
                    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 new InjectionMetadata(clazz, elements);
    }

特定注解指的就是@Autowired @Value @Inject(较少用) @Qualifier注解是跟@Autowired注解搭配使用的 单独使用是不起作用的
特定的数据结构指的就是InjectionMetadata 博主前面说过 阅读源代码千万不要对这样的代码感到畏惧 就把他当成一个包装类或者工具类就可以了 为了完成或者包装某些功能写出的一些类而已
再具体的代码就不带着一起看了 相信读者阅读这样的代码应该没有任何问题
我们接着看下另外一个方法postProcessPropertyValues(xxx)
这个方法的执行的时间节点是在populateBean(xxx)之后

    @Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

        //从缓存中读取出
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            //注入
            metadata.inject(bean, beanName, pvs);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
        }
        return pvs;
    }

postProcessMergedBeanDefinition(xxx)方法中把循环检查出的特定注解修饰的field``method以特定的数据结构以beanName为key保存在了一个map中 在postProcessPropertyValues(xxx)方法中取出来处理
这里我们以field注入讲解 进入方法AutowiredFieldElement#inject(xxx)

        @Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
            Field field = (Field) this.member;
            try {
                Object value;
                if (this.cached) {
                    value = resolvedCachedArgument(beanName, this.cachedFieldValue);
                }
                else {
                    DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
                    Set autowiredBeanNames = new LinkedHashSet(1);
                    TypeConverter typeConverter = beanFactory.getTypeConverter();
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
                    synchronized (this) {
                        if (!this.cached) {
                            if (value != null || this.required) {
                                this.cachedFieldValue = desc;
                                registerDependentBeans(beanName, autowiredBeanNames);
                                if (autowiredBeanNames.size() == 1) {
                                    String autowiredBeanName = autowiredBeanNames.iterator().next();
                                    if (beanFactory.containsBean(autowiredBeanName)) {
                                        if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                            this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
                                        }
                                    }
                                }
                            }
                            else {
                                this.cachedFieldValue = null;
                            }
                            this.cached = true;
                        }
                    }
                }
                // 通过反射设置值
                if (value != null) {
                    ReflectionUtils.makeAccessible(field);
                    field.set(bean, value);
                }
            }
            catch (Throwable ex) {
                throw new BeanCreationException("Could not autowire field: " + field, ex);
            }
        }

这里 DependencyDescriptor同样是为了方便操作 对field进行的包装
beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter)方法完成解析 最后会调用doResolveDependency(xxx)方法

    protected Object doResolveDependency(DependencyDescriptor descriptor, Class type, String beanName,
            Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
        //处理@Value注解
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                // 这里会处理掉"${}"
                String strVal = resolveEmbeddedValue((String) value);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            return (descriptor.getField() != null ?
                    converter.convertIfNecessary(value, type, descriptor.getField()) :
                    converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
        }
        //处理@Autowired注解
        if (type.isArray()) {
            Class componentType = type.getComponentType();
            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor);
            if (matchingBeans.isEmpty()) {
                if (descriptor.isRequired()) {
                    raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor);
                }
                return null;
            }
            if (autowiredBeanNames != null) {
                autowiredBeanNames.addAll(matchingBeans.keySet());
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            return converter.convertIfNecessary(matchingBeans.values(), type);
        }
        else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
            Class elementType = descriptor.getCollectionType();
            if (elementType == null) {
                if (descriptor.isRequired()) {
                    throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]");
                }
                return null;
            }
            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor);
            if (matchingBeans.isEmpty()) {
                if (descriptor.isRequired()) {
                    raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor);
                }
                return null;
            }
            if (autowiredBeanNames != null) {
                autowiredBeanNames.addAll(matchingBeans.keySet());
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            return converter.convertIfNecessary(matchingBeans.values(), type);
        }
        else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
            Class keyType = descriptor.getMapKeyType();
            if (keyType == null || !String.class.isAssignableFrom(keyType)) {
                if (descriptor.isRequired()) {
                    throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
                            "] must be assignable to [java.lang.String]");
                }
                return null;
            }
            Class valueType = descriptor.getMapValueType();
            if (valueType == null) {
                if (descriptor.isRequired()) {
                    throw new FatalBeanException("No value type declared for map [" + type.getName() + "]");
                }
                return null;
            }
            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor);
            if (matchingBeans.isEmpty()) {
                if (descriptor.isRequired()) {
                    raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor);
                }
                return null;
            }
            if (autowiredBeanNames != null) {
                autowiredBeanNames.addAll(matchingBeans.keySet());
            }
            return matchingBeans;
        }
        else {
            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
            if (matchingBeans.isEmpty()) {
                if (descriptor.isRequired()) {
                    raiseNoSuchBeanDefinitionException(type, "", descriptor);
                }
                return null;
            }
            if (matchingBeans.size() > 1) {
                String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
                if (primaryBeanName == null) {
                    throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
                }
                if (autowiredBeanNames != null) {
                    autowiredBeanNames.add(primaryBeanName);
                }
                return matchingBeans.get(primaryBeanName);
            }
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            if (autowiredBeanNames != null) {
                autowiredBeanNames.add(entry.getKey());
            }
            return entry.getValue();
        }
    }

我们先看对@Value注解的解析
@Value注解有两种使用方法 除了可以直接指出我们想要的值外 还可以

@Value("${xxx}")

这个功能在spring3.x以后才能使用 3.x以前的版本取出来的就是${xxx}而不会再被解析 其背后的原因就是3.x以后的代码 通过PropertyPlaceholderConfigurer向beanFactory加入了一个处理器 PropertyPlaceholderConfigurer源码解析 这篇文章的最后又指出

getAutowireCandidateResolver()这个方法返回的是在初始化beanFactory的过程中加入的QualifierAnnotationAutowireCandidateResolver

    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
        //设置Qualifier注解解析类
        beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
    }

QualifierAnnotationAutowireCandidateResolver#getSuggestedValue(xxx)

    public Object getSuggestedValue(DependencyDescriptor descriptor) {
        Object value = findValue(descriptor.getAnnotations());
        if (value == null) {
            MethodParameter methodParam = descriptor.getMethodParameter();
            if (methodParam != null) {
                value = findValue(methodParam.getMethodAnnotations());
            }
        }
        return value;
    }

如果有@Value注解的话 返回设置的value值 如果没有就返回null
如果返回的value不为null的话 就需要进一步处理这个原始值 因为这个值可能不是我们最终想要的 例如我们前面讲到的@Value("${xxx}") 这个时候返回的就是${xxx} 显然不是我们想要的 当然spring还提供了处理表达式的支持 这里不再讲解
最后再通过converter处理一遍返回

如果返回的是null 说明没有@Value注解 spring增加了对array collection map注入的支持 有兴趣的可以看看 我们就选一个最简单最基础的注入为例来讲解 @Autowired的工作原理 也就是最后一个else分支

{
            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
            if (matchingBeans.isEmpty()) {
                if (descriptor.isRequired()) {
                    raiseNoSuchBeanDefinitionException(type, "", descriptor);
                }
                return null;
            }
            if (matchingBeans.size() > 1) {
                String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
                if (primaryBeanName == null) {
                    throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
                }
                if (autowiredBeanNames != null) {
                    autowiredBeanNames.add(primaryBeanName);
                }
                return matchingBeans.get(primaryBeanName);
            }
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            if (autowiredBeanNames != null) {
                autowiredBeanNames.add(entry.getKey());
            }
            return entry.getValue();
        }

进入findAutowireCandidates(xxx)方法

    protected Map<String, Object> findAutowireCandidates(
            String beanName, Class requiredType, DependencyDescriptor descriptor) {

        String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this, requiredType, true, descriptor.isEager());
        Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
        for (Class autowiringType : this.resolvableDependencies.keySet()) {
            if (autowiringType.isAssignableFrom(requiredType)) {
                Object autowiringValue = this.resolvableDependencies.get(autowiringType);
                autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
                if (requiredType.isInstance(autowiringValue)) {
                    result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
                    break;
                }
            }
        }
        for (String candidateName : candidateNames) {
            if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
                result.put(candidateName, getBean(candidateName));
            }
        }
        return result;
    }

首先从beanFactory中取出所有符合requiredType类型的bean的名称 requiredType是要被注入的字段的类型(其实这一步就已经完成了@Autowired注解的功能) 然后循环判断这些bean中有哪些是符合条件的 哪些是不符合条件的(想一想为什么还要继续判断?)

    public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
            throws NoSuchBeanDefinitionException {

        // Consider FactoryBeans as autowiring candidates.
        boolean isFactoryBean = (descriptor != null && descriptor.getDependencyType() != null &&
                FactoryBean.class.isAssignableFrom(descriptor.getDependencyType()));
        if (isFactoryBean) {
            beanName = BeanFactoryUtils.transformedBeanName(beanName);
        }

        if (containsBeanDefinition(beanName)) {
            return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanName), descriptor);
        }
        else if (containsSingleton(beanName)) {
            return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor);
        }
        else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) {
            // No bean definition found in this factory -> delegate to parent.
            return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor);
        }
        else {
            return true;
        }
    }

这个方法里面是考虑是很多中情况了 比如是不是factoryBean等 这里我们还是以最简单的情况分析
最后会进入方法QualifierAnnotationAutowireCandidateResolver#isAutowireCandidate(xxx)方法

    public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
        if (!bdHolder.getBeanDefinition().isAutowireCandidate()) {
            // 如果已经设置了非候选类 直接返回
            return false;
        }
        if (descriptor == null) {
            // no qualification necessary
            return true;
        }
        boolean match = checkQualifiers(bdHolder, descriptor.getAnnotations());
        if (match) {
            MethodParameter methodParam = descriptor.getMethodParameter();
            if (methodParam != null) {
                Method method = methodParam.getMethod();
                if (method == null || void.class.equals(method.getReturnType())) {
                    match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
                }
            }
        }
        return match;
    }

对于@Autowired注解 是按类型匹配的 前面已经筛选出了beanFactory中所有的符合条件的类型 这里为什么还要继续筛选呢 原因就是可能还会有@Qualifier注解

    protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) {
        if (ObjectUtils.isEmpty(annotationsToSearch)) {
            return true;
        }
        SimpleTypeConverter typeConverter = new SimpleTypeConverter();
        for (Annotation annotation : annotationsToSearch) {
            Classextends Annotation> type = annotation.annotationType();
            boolean checkMeta = true;
            boolean fallbackToMeta = false;
            if (isQualifier(type)) {
                if (!checkQualifier(bdHolder, annotation, typeConverter)) {
                    fallbackToMeta = true;
                }
                else {
                    checkMeta = false;
                }
            }
            if (checkMeta) {
                boolean foundMeta = false;
                for (Annotation metaAnn : type.getAnnotations()) {
                    Classextends Annotation> metaType = metaAnn.annotationType();
                    if (isQualifier(metaType)) {
                        foundMeta = true;
                        // Only accept fallback match if @Qualifier annotation has a value...
                        // Otherwise it is just a marker for a custom qualifier annotation.
                        if ((fallbackToMeta && StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
                                !checkQualifier(bdHolder, metaAnn, typeConverter)) {
                            return false;
                        }
                    }
                }
                if (fallbackToMeta && !foundMeta) {
                    return false;
                }
            }
        }
        return true;
    }

这个方法做的工作就是检查有没有@Qualifier注解 如果有的话 再检查是不是符合条件
例如虽然有多个候选的符合条件的类型 但是@Qualifier指出了特定的名称 这样就实现了按照名称的匹配
最后返回通过最终筛选的bean

你可能感兴趣的:(Spring源码研究)