注解原理

@Autowired原理

  @Autowired注解表示自动注入,定义在属性上,set方法上,构造方法上等。使用其进行标注后Spring将自动注入对应的内容,默认是按照类型进行注入。使用@Autowired标注进行注入的内容,默认是@Required的,即在对应bean完全初始化后对应的属性不能为空,必须进行注入。

   Spring在启动阶段,先实例化bean,再对bean进行初始化操作。在初始化阶段,通过调用Bean后置处理来完成对属性赋值等操作,实现@Autowired的功能,通过AutowiredAnnotationBeanPostProcessor后置处理器来完成。

   AutowiredAnnotationBeanPostProcessor什么时候被加入到Spring容器当中?

  调用AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class)启动容器的时候,在构造方法中会调用到this()方法,在this()方法中最终会调用到registerAnnotationConfigProcessors()方法,在该方法中,Spring会向容器注册7个Spring内置的Bean,其中就包括AutowiredAnnotationBeanPostProcessor。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

    // 省略部分代码...
    
    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    // 注册AutowiredAnnotationBeanPostProcessor,这个bean的后置处理器用来处理@Autowired的注入
    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));
    }

    // 注册CommonAnnotationBeanPostProcessor,用来处理如@Resource等符合JSR-250规范的注解
    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));
    }
    return beanDefs;
}

  AutowiredAnnotationBeanPostProcessor是何时被调用的呢?

  Spring在创建bean的过程中,最终会调用到doCreateBean()方法,在doCreateBean()方法中会调用populateBean()方法,来为bean进行属性填充,完成自动装配等工作。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (hasInstAwareBpps || needsDepCheck) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 执行后置处理器,填充属性,完成自动装配
                    // 在这里会调用到AutowiredAnnotationBeanPostProcessor
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
    }
}

  调用到AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues()方法,在该方法中就会进行@Autowired注解的解析,然后实现自动装配。

  先调用findAutowiringMetadata()方法解析出bean中带有@Autowired注解、@Inject和@Value注解的属性和方法。然后调用metadata.inject()方法,进行属性填充。

public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
    // 解析出bean中带有@Autowired注解、@Inject和@Value注解的属性和方法
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 自动装配,实现依赖注入
        metadata.inject(bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}

metadata.inject()

  属性上加Autowired注解的,经过解析后,将字段解析为AutowiredFieldElement类型;如果是方法上加Autowired注解,则会解析为AutowiredMethodElement类型。它们均是InjectedElement类的子类,里面封装属性名,属性类型等信息。

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Field field = (Field) this.member;
        Object value;
        // 判断缓存(第一次注入userService的时候,肯定没有缓存,所以会进入到else里面)
        // 当第一次注入完成后,会将userService缓存到cachedFieldValue这个属性中,
        // 这样当其他的类同样需要注入userService时,就会从这儿的缓存当中读取了。
        if (this.cached) {
            value = resolvedCachedArgument(beanName, this.cachedFieldValue);
        }
        else {
            DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
            desc.setContainingClass(bean.getClass());
            Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
            TypeConverter typeConverter = beanFactory.getTypeConverter();
            try {
                // 通过beanFactory.resolveDependency()方法,来从容器中找到userService属性对应的值。
                value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
            }
            catch (BeansException ex) {
                throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
            }
            // 省略部分代码...
            // 省略的这部分代码就是将value进行缓存,缓存到cachedFieldValue属性中
        }
        if (value != null) {
            // 通过Java的反射,为属性进行复制
            ReflectionUtils.makeAccessible(field);
            field.set(bean, value);
        }
    }
}

  doResolveDependency()源码

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }
        // 省略部分不重要的代码...
        
        // 属性的类型可能是数组、集合、Map类型,所以这一步是处理数组类型、Collection、Map类型的属性
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }
        // 根据需要注入的类型type,从容器中找到有哪些匹配的Bean。
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        // 如果从容器中没有找到,且@Autowired的required属性为true,那么则会抛出异常
        if (matchingBeans.isEmpty()) {
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;

        // 先根据类型匹配出可以依赖注入的bean的Class,如果匹配出多个,则再根据属性名匹配
        if (matchingBeans.size() > 1) {
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                    // 当匹配到多个bean的Class,但是却不知道要选择哪一个注入时,就会抛出异常
                    return descriptor.resolveNotUnique(type, matchingBeans);
                }
                else {
                    // In case of an optional Collection/Map, silently ignore a non-unique case:
                    // possibly it was meant to be an empty collection of multiple regular beans
                    // (before 4.3 in particular when we didn't even look for collection beans).
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
            // We have exactly one match.
            // 只匹配到一个,则就使用匹配到这个类型
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }

        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        // 此处instanceCandidate = UserServiceImpl.class
        if (instanceCandidate instanceof Class) {
            // instanceCandidate是注入属性的类型,这个需要根据Class,通过FactoryBean的getBean()方法,创建该类型的单例bean
            instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
        }
        Object result = instanceCandidate;
        if (result instanceof NullBean) {
            // 如果没从容器中找到对应的bean,则需要判断属性值是否是必须注入的,
            // 即@Autowired(required=false/true),如果为true,则抛异常,这就是经常项目启动时,我们看到的异常
            if (isRequired(descriptor)) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            result = null;
        }
        if (!ClassUtils.isAssignableValue(type, result)) {
            throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
        }
        return result;
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

  resolveMultipleBeans()方法的部分源码

private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
    Class<?> type = descriptor.getDependencyType();
    // 处理数组类型
    if (type.isArray()) {
        // findAutowireCandidates最终会调用getBean()方法
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
                new MultiElementDescriptor(descriptor));
        return result;
    }
    // 处理集合类型
    else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
        // findAutowireCandidates最终会调用getBean()方法
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
                new MultiElementDescriptor(descriptor));
        return result;
    }
    // 处理Map类型
    else if (Map.class == type) {
        // findAutowireCandidates最终会调用getBean()方法
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
                new MultiElementDescriptor(descriptor));
        return matchingBeans;
    }
    else {
        return null;
    }
}
  • 如果需要注入的属性是普通类型(非数组、集合、Map),那么方法会继续向下执行,会调用下面一行代码,根据属性的类型来查找bean。
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

  调用findAutowireCandidates()方法,该方法最终会调用getBean()方法,所以它会从容器中找到对应类型的bean,如果容器没有找到对应类型的Bean,且属性是必须注入的,即Autowired注解的required属性为true,那么就会抛出异常,这个异常就是我们经常看见的:NoSuchBeanDefinitionException

// 如果容器汇总没有找到指定类型的bean,那么matchingBeans属性就是空的
if (matchingBeans.isEmpty()) {
    if (isRequired(descriptor)) {
        // 抛出异常
        raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    }
    return null;
}

  

  

 

 

posted on 2018-10-25 22:43  溪水静幽  阅读(299)  评论(0)    收藏  举报