溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

原創(chuàng)001 | 搭上SpringBoot自動(dòng)注入源碼分析專車

發(fā)布時(shí)間:2020-06-20 11:43:04 來(lái)源:網(wǎng)絡(luò) 閱讀:2878 作者:師長(zhǎng)學(xué)不動(dòng)了 欄目:編程語(yǔ)言

本系列為SpringBoot深度源碼專車系列,第一篇發(fā)車!

原創(chuàng)001 | 搭上SpringBoot自動(dòng)注入源碼分析專車

專車介紹

該趟專車是開(kāi)往Spring Boot自動(dòng)注入原理源碼分析的專車

專車問(wèn)題

  • Spring Boot何時(shí)注入@Autowired標(biāo)注的屬性?
  • 如果注入類型的Bean存在多個(gè)Spring Boot是如何處理的?

專車示例

  • 定義接口
public interface PersonService {

    String hello(String name);
}
  • 定義接口的一個(gè)實(shí)現(xiàn)
@Service(value = "studentService")
public class StudentServiceImpl implements PersonService {

    @Override
    public String hello(String name) {
        return "[student service] hello " + name;
    }
}
  • 定義接口的另一個(gè)實(shí)現(xiàn)
@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);
    }
}

以上示例代碼很簡(jiǎn)單,創(chuàng)建了一個(gè)接口,接口有兩個(gè)實(shí)現(xiàn)類,然后在控制器中注入實(shí)現(xiàn)類,從而完成業(yè)務(wù)方法的調(diào)用。接下來(lái)我們就開(kāi)始對(duì)源碼進(jìn)行分析

專車分析

在分析代碼之前我們先回憶一下操作對(duì)象的步驟:

  • 首先我們會(huì)實(shí)例化一個(gè)對(duì)象
  • 然后調(diào)用對(duì)象的set方法來(lái)設(shè)置對(duì)象的屬性

有了上面的基礎(chǔ)知識(shí),接下來(lái)就開(kāi)始揭秘旅程

尋找入口

在分析源碼的時(shí)候最關(guān)鍵的一步就是尋找程序的入口,有了入口我們就成功了一半,那么如何尋找程序的入口?針對(duì)此處的源碼分析,我們可以在TestController類上打一個(gè)斷點(diǎn),然后查看調(diào)用鏈
原創(chuàng)001 | 搭上SpringBoot自動(dòng)注入源碼分析專車

基于調(diào)用鏈路,我們看到有一個(gè)doCreateBean方法,該方法就是用來(lái)創(chuàng)建bean的,也就是我們上面提到的實(shí)例化對(duì)象部分

實(shí)例化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) {
        // 創(chuàng)建bean
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    // ...省略部分代碼
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 填充bean,也就是我們上面提到的調(diào)用對(duì)象的set方法設(shè)置對(duì)象屬性
        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;
                // 通過(guò)斷點(diǎn)分析我們可以得知此處調(diào)用的是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) {
    // 查找當(dāng)前bean需要注入的元數(shù)據(jù)信息,以TestController為例,那么需要注入的就是studentService和teacherService兩個(gè)屬性
    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;
    // 屬性對(duì)應(yīng)的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);
        // 給屬性設(shè)置值,完成注入功能
        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 {
        // ...省略代碼

        // 解析多個(gè)Bean,比如Array、List、Map類型,有興趣可以自己查看分析
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }

        // 根據(jù)類型獲取候選對(duì)象,針對(duì)studentService而言,該屬性的類型為PersonService
        // PersonService有2個(gè)實(shí)現(xiàn)類,StudentServiceImpl和TeacherServiceImpl
        // 所以此處獲取結(jié)果為StudentServiceImpl對(duì)象和TeacherServiceImpl對(duì)象
        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;
        // 重點(diǎn)處理,如果存在多個(gè)匹配的bean
        if (matchingBeans.size() > 1) {
            // 從已經(jīng)匹配的bean中選擇一個(gè)符合的bean
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                // 如果bean必須注入或者存在多個(gè)匹配的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;
                }
            }
            // 根據(jù)bean名稱獲取對(duì)應(yīng)的示例
            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());
        }
        // 返回對(duì)應(yīng)的示例對(duì)象
        return result;
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

此處主要根據(jù)類型獲取所有匹配的bean,如果匹配的bean有多個(gè),那么最后會(huì)選擇一個(gè)符合條件的bean名稱,然后將對(duì)應(yīng)的bena實(shí)例返回,調(diào)用set方法進(jìn)行進(jìn)行注入,到此注入的原理本該結(jié)束了。但是還是要分析一下Spring Boot是如何選擇出符合條件的bean?

選擇符合條件的bean DefaultListableBeanFactory#determineAutowireCandidate

protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
    Class<?> requiredType = descriptor.getDependencyType();
    // 如果bean對(duì)應(yīng)的primary屬性為true,則返回bean對(duì)應(yīng)的名稱
    String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
    if (primaryCandidate != null) {
        return primaryCandidate;
    }
    // 如果候選bean使用javax.annotation.Priority標(biāo)注,返回高優(yōu)先級(jí)bean對(duì)應(yīng)的名稱
    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名稱總結(jié):

  • 依據(jù)Bean的primary屬性
  • 依據(jù)javax.annotation.Priority
  • 依據(jù)注入屬性的名稱

專車總結(jié)

  • Bean實(shí)例化完成后,填充Bean
  • 調(diào)用AutowiredAnnotationBeanPostProcessor#postProcessProperties處理屬性
  • 獲取所有需要注入的屬性
  • 根據(jù)注入屬性的類型從IOC容器中查找匹配實(shí)例
  • 如果匹配實(shí)例存在多個(gè),根據(jù)primary屬性--->javax.annotation.Priority注解--->注入屬性名稱依次過(guò)濾,返回符合條件的Bean名稱
  • 過(guò)濾之后,存在一個(gè)符合條件的Bean名稱,則返回對(duì)應(yīng)的實(shí)例,否則拋出異常

專車回顧

回顧一下開(kāi)頭的2個(gè)問(wèn)題:

  • Spring Boot何時(shí)注入@Autowired標(biāo)注的屬性?
  • 如果注入類型的Bean存在多個(gè)Spring Boot是如何處理的?

第一個(gè)問(wèn)題:是在Bean實(shí)例化后,填充Bean的時(shí)候注入@Autowired標(biāo)注的屬性

第二個(gè)問(wèn)題:如果存在多個(gè)類型的Bean,會(huì)根據(jù)primary--->javax.annotation.Priority--->名稱依次過(guò)濾,得到最終匹配的bean名稱

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI