注解原理
@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; }
浙公网安备 33010602011771号