扫描下方二维码或者微信搜索公众号 菜鸟飞呀飞
,即可关注微信公众号,阅读更多Spring源码分析和Java并发编程文章。
在平时工作中,只要是做Java开发,基本都离不开Spring框架,Spring的一大核心功能就是IOC,它能帮助我们实现自动装配,基本上每天我们都会使用到@Autowired注解来为我们自动装配属性,那么你知道Autowired注解的原理吗?在阅读本文之前,可以先思考一下以下几个问题。
先按照如下示例搭建一下本文的demo工程
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.8.RELEASE</version> </dependency> 复制代码
@Configuration @ComponentScan("com.tiantang.study") public class AppConfig { } 复制代码
public interface UserService { } 复制代码
@Service public class UserServiceImpl implements UserService { } 复制代码
public interface OrderService { void query(); } 复制代码
@Service public class OrderServiceImpl implements OrderService { @Autowired private UserService userService; public void query(){ System.out.println(userService); } } 复制代码
public class MainApplication { public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); OrderService orderService = applicationContext.getBean(OrderService.class); orderService.query(); } } 复制代码
通过上面的demo我们完成了对OrderServiceImpl的自动装配,为其属性userService完成了赋值操作,那么Spring是如何通过@Autowired来实现赋值的呢?我们知道,Spring在容器启动阶段,会先实例化bean,然后再对bean进行初始化操作。在初始化阶段,会通过调用Bean后置处理来完成对属性的赋值等操作,那么同理,要想实现@Autowired的功能,肯定也是通过后置处理器来完成的。这个后置处理器就是AutowiredAnnotationBeanPostProcessor。接下来我们就来看看这个类的源码。
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class)
启动容器的时候,在构造方法中会调用到 this()
方法,在 this()
方法中最终会调用到 registerAnnotationConfigProcessors()
方法,在该方法中,Spring会向容器注册7个Spring内置的Bean,其中就包括AutowiredAnnotationBeanPostProcessor。如果想详细了解Spring容器的启动过程,可以参考笔者的另一篇文章: Spring源码系列之容器启动流程 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是何时被调用的呢?
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; } } } } } } 复制代码
public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { // 解析出bean中带有@Autowired注解、@Inject和@Value注解的属性和方法 // 对于本文的demo而言,在此处就会解析出OrderServiceImpl类上的userService属性 // 至于如何解析的,findAutowiringMetadata()方法比较复杂,这里就不展开了,Spring中提供了很多对注解等元数据信息读取的方法,进行了大量的封装。 // 如果不是自己亲自参与开发Spring的话,很难摸透它封装的那些数据结构。 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; } 复制代码
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4); 复制代码
public AutowiredAnnotationBeanPostProcessor() { // 添加@Autowired this.autowiredAnnotationTypes.add(Autowired.class); // 添加@Value this.autowiredAnnotationTypes.add(Value.class); try { // 如果项目中引入了JSR-330相关的jar包,那么就会添加@Inject this.autowiredAnnotationTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); } catch (ClassNotFoundException ex) { } } 复制代码
beanFactory.resolveDependency()
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); } } } 复制代码
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); } } 复制代码
@Autowired private UserService[] userServiceArray; @Autowired private List<UserService> userServiceList; @Autowired private Map<String,UserService> userServiceMap; 复制代码
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<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); 复制代码
NoSuchBeanDefinitionException
。 // 如果容器汇总没有找到指定类型的bean,那么matchingBeans属性就是空的 if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { // 抛出异常 raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } 复制代码
if (matchingBeans.size() > 1) { // 判断应该使用哪一个bean autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { // 当匹配到多个bean的Class,但是却不知道要选择哪一个注入时,就会抛出异常 return descriptor.resolveNotUnique(type, matchingBeans); } else { return null; } } instanceCandidate = matchingBeans.get(autowiredBeanName); } 复制代码
NoUniqueBeanDefinitionException
。 "expected single matching bean but found " + beanNamesFound.size() + ": " + StringUtils.collectionToCommaDelimitedString(beanNamesFound) 复制代码
NoUniqueBeanDefinitionException 这就是我们平常所说的@Autowired注解是先根据类型注入,当碰到多个相同类型时,就会根据属性名注入。它的实现原理就是在如下代码中实现的。
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) { Class<?> requiredType = descriptor.getDependencyType(); // 根据Primary注解来决定优先注入哪个bean String primaryCandidate = determinePrimaryCandidate(candidates, requiredType); if (primaryCandidate != null) { return primaryCandidate; } // 根据@Priority注解的优先级来决定注入哪个bean String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType); if (priorityCandidate != null) { return priorityCandidate; } // 如果既没有指定@Primary,也没有指定@Priority,那么就会根据属性的名称来决定注入哪个bean // 如果要注入的属性的名称与Bean的beanName相同或者别名相同,那么会就会优先注入这个Bean for (Map.Entry<String, Object> entry : candidates.entrySet()) { String candidateName = entry.getKey(); Object beanInstance = entry.getValue(); if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) || matchesBeanName(candidateName, descriptor.getDependencyName())) { return candidateName; } } // 前面三种情况都没有确定要注入哪个bean,那么就返回null。当返回null时,那么就会再调用该方法出抛出异常。 return null; } 复制代码
AutowiredFeildElement.inject()
在文章的开头,我问了一个问题:自动装配的模型是什么?有哪几种?和Autowired注解有什么关联?实际上这个问题,和今天的主角AutowiredAnnotationBeanPostProcessor没有任何关系。但是为什么又把它放在这篇文章中提出来呢?这是因为@Autowired注解的实现原理和自动装配模型极为容易混淆。
public enum Autowire { NO(AutowireCapableBeanFactory.AUTOWIRE_NO), BY_NAME(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME), BY_TYPE(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE); } 复制代码
<bean id="orderService" class="com.tiantang.study.service.impl.OrderServiceImpl" autowire="byName"> </bean> 复制代码
@Bean(autowire = Autowire.BY_NAME) public OrderService orderService(){ return new OrderServiceImpl(); } 复制代码
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 判断bean的注入模型是byName,还是byType。 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 对于MyBatis而言,Mapper在实例化之后,会填充属性,这个时候,需要找到MapperFactoryBean有哪些属性需要填充 // 在Mapper的BeanDefinition初始化时,默认添加了一个属性,addToConfig // 在下面的if逻辑中,执行完autowireByType()方法后,会找出另外另个需要填充的属性,分别是sqlSessionFactory和sqlSessionTemplate if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); 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; // 第六次执行后置处理器,填充属性,完成自动装配 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } if (pvs != null) { // 实现通过byName或者byType类型的属性注入 applyPropertyValues(beanName, mbd, bw, pvs); } } 复制代码
// 判断bean的注入模型是byName,还是byType。 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 对于MyBatis而言,Mapper在实例化之后,会填充属性,这个时候,需要找到MapperFactoryBean有哪些属性需要填充 // 在Mapper的BeanDefinition初始化时,默认添加了一个属性,addToConfig // 在下面的if逻辑中,执行完autowireByType()方法后,会找出另外另个需要填充的属性,分别是sqlSessionFactory和sqlSessionTemplate if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } 复制代码
applyPropertyValues()
方法,然后将其填充到Bean当中。 sqlSessionFactory
、 sqlSessionTemplate
,然后为这两个属性赋值。 private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { GenericBeanDefinition definition; for (BeanDefinitionHolder holder : beanDefinitions) { definition = (GenericBeanDefinition) holder.getBeanDefinition(); // 指定MapperFactoryBean的自动装配模型为AUTOWIRE_BY_TYPE definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); } } 复制代码
总结之前,先回答一下文章开头的三个问题。1)@Autowired注解的实现是通过后置处理器AutowiredAnnotationBeanPostProcessor类的postProcessPropertyValues()方法实现的。2)当自动装配时,从容器中如果发现有多个同类型的属性时,@Autowired注解会先根据类型判断,然后根据@Primary、@Priority注解判断,最后根据属性名与beanName是否相等来判断,如果还是不能决定注入哪一个bean时,就会抛出NoUniqueBeanDefinitionException异常。3)@Autowired自动装配中byName、byType与自动装配的模型中的byName、byTYpe没有任何关系,两者含义完全不一样,前者是实现技术的手段,后者是用来定义BeanDefiniton中autowireMode属性的值的类型。