栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java > SpringBoot

001 | 搭上SpringBoot自动注入源码分析专车

SpringBoot 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

001 | 搭上SpringBoot自动注入源码分析专车

前言

如果这是你第二次看到师长,说明你在觊觎我的美色!

点赞+关注再看,养成习惯

没别的意思,就是需要你的窥屏_

本系列为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 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 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 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 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 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 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 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名称

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号