前言
如果这是你第二次看到师长的文章, 说明你在觊觎我的美色! O(∩_∩)O 哈哈~
点赞 + 关注再看, 养成习惯
没别的意思, 就是需要你的窥屏 ^_^
本系列为 SpringBoot 深度源码专车系列, 第一篇发车!
专车介绍
该趟专车是开往 Spring Boot 自动注入原理源码分析的专车
专车问题
Spring Boot 何时注入 @Autowired 标注的属性?
如果注入类型的 Bean 存在多个 Spring Boot 是如何处理的?
专车示例
定义接口
- public interface PersonService {
- String hello(String name);
- }
定义接口的一个实现
@Service(value = "studentService") public class StudentServiceImpl implements PersonService { @Override public String hello(String name) { return "[student service] hello" + name; } }
定义接口的另一个实现
@Service(value = "teacherService") public class TeacherServiceImpl implements PersonService { @Override public String hello(String name) { return "[teacher service] hello" + name; } }
定义控制器
@RestController public class TestController { @Autowired private PersonService studentService; @Autowired private PersonService teacherService; @GetMapping("/hello") public String hello(@RequestParam(name = "name") String name) { return studentService.hello(name) + "=======>" + teacherService.hello(name); } }
以上示例代码很简单, 创建了一个接口, 接口有两个实现类, 然后在控制器中注入实现类, 从而完成业务方法的调用. 接下来我们就开始对源码进行分析
专车分析
在分析代码之前我们先回忆一下操作对象的步骤:
首先我们会实例化一个对象
然后调用对象的 set 方法来设置对象的属性
有了上面的基础知识, 接下来就开始揭秘旅程
寻找入口
在分析源码的时候最关键的一步就是寻找程序的入口, 有了入口我们就成功了一半, 那么如何寻找程序的入口? 针对此处的源码分析, 我们可以在 TestController 类上打一个断点, 然后查看调用链
基于调用链路, 我们看到有一个 doCreateBean 方法, 该方法就是用来创建 bean 的, 也就是我们上面提到的实例化对象部分
实例化 Bean
AbstractAutowireCapableBeanFactory#doCreateBean protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 创建 bean instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); // ... 省略部分代码 // Initialize the bean instance. Object exposedObject = bean; try { // 填充 bean, 也就是我们上面提到的调用对象的 set 方法设置对象属性 populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } // ... 省略部分代码 return exposedObject; }
填充 bean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // ... 省略代码 PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } // 遍历所有的后置处理器 for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 通过断点分析我们可以得知此处调用的是 AutowiredAnnotationBeanPostProcessor#postProcessProperties PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
处理属性
AutowiredAnnotationBeanPostProcessor#postProcessProperties public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 查找当前 bean 需要注入的元数据信息, 以 TestController 为例, 那么需要注入的就是 studentService 和 teacherService 两个属性 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; }
注入属性 AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // 获取属性, 此处的属性就是 studentService Field field = (Field) this.member; // 属性对应的 value Object value; 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); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { // 解析属性依赖 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } 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) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { ReflectionUtils.makeAccessible(field); // 给属性设置值, 完成注入功能 field.set(bean, value); } }
解析属性依赖 DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); if (Optional.class == descriptor.getDependencyType()) { return createOptionalDependency(descriptor, requestingBeanName); } else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider(descriptor, requestingBeanName); } else if (javaxInjectProviderClass == descriptor.getDependencyType()) { return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); } else { Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null) { // 解析依赖 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } }
解析属性依赖 DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { // ... 省略代码 // 解析多个 Bean, 比如 Array,List,Map 类型, 有兴趣可以自己查看分析 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } // 根据类型获取候选对象, 针对 studentService 而言, 该属性的类型为 PersonService // PersonService 有 2 个实现类, StudentServiceImpl 和 TeacherServiceImpl // 所以此处获取结果为 StudentServiceImpl 对象和 TeacherServiceImpl 对象 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; // 重点处理, 如果存在多个匹配的 bean if (matchingBeans.size()> 1) { // 从已经匹配的 bean 中选择一个符合的 bean autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { // 如果 bean 必须注入或者存在多个匹配的 bean, 则抛出异常 if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(descriptor.getResolvableType(), 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; } } // 根据 bean 名称获取对应的示例 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); } if (instanceCandidate instanceof Class) { instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } Object result = instanceCandidate; if (result instanceof NullBean) { 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); } }
此处主要根据类型获取所有匹配的 bean, 如果匹配的 bean 有多个, 那么最后会选择一个符合条件的 bean 名称, 然后将对应的 bena 实例返回, 调用 set 方法进行进行注入, 到此注入的原理本该结束了. 但是还是要分析一下 Spring Boot 是如何选择出符合条件的 bean?
选择符合条件的 bean DefaultListableBeanFactory#determineAutowireCandidate
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) { Class<?> requiredType = descriptor.getDependencyType(); // 如果 bean 对应的 primary 属性为 true, 则返回 bean 对应的名称 String primaryCandidate = determinePrimaryCandidate(candidates, requiredType); if (primaryCandidate != null) { return primaryCandidate; } // 如果候选 bean 使用 javax.annotation.Priority 标注, 返回高优先级 bean 对应的名称 String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType); if (priorityCandidate != null) { return priorityCandidate; } // Fallback // 如果匹配 bean 的名称和需要注入的属性名称一致, 则返回匹配 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; } } return null; }
获取符合条件 bean 名称总结:
依据 Bean 的 primary 属性
依据 javax.annotation.Priority
依据注入属性的名称
专车总结
Bean 实例化完成后, 填充 Bean
调用 AutowiredAnnotationBeanPostProcessor#postProcessProperties 处理属性
获取所有需要注入的属性
根据注入属性的类型从 IoC 容器中查找匹配实例
如果匹配实例存在多个, 根据 primary 属性 --->javax.annotation.Priority 注解 ---> 注入属性名称依次过滤, 返回符合条件的 Bean 名称
过滤之后, 存在一个符合条件的 Bean 名称, 则返回对应的实例, 否则抛出异常
专车回顾
回顾一下开头的 2 个问题:
Spring Boot 何时注入 @Autowired 标注的属性?
如果注入类型的 Bean 存在多个 Spring Boot 是如何处理的?
第一个问题: 是在 Bean 实例化后, 填充 Bean 的时候注入 @Autowired 标注的属性
第二个问题: 如果存在多个类型的 Bean, 会根据 primary--->javax.annotation.Priority---> 名称依次过滤, 得到最终匹配的 bean 名称
来源: https://www.cnblogs.com/shizhang/p/12001119.html