Autowire原理

Spring5的@Autowire原理分析

Autowire注解

從Autowire注解點(diǎn)進(jìn)去看

注釋的第一句話說是將構(gòu)造函數(shù)拳话、字段诵肛、setter方法或者配置方法通過由Spring依賴注入工具自動(dòng)裝入

在注釋的最后 說這個(gè)注解是通過 BeanPostProcessor 這個(gè)接口進(jìn)行的

最后的實(shí)現(xiàn)類是 AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor 類

public class AutowiredAnnotationBeanPostProcessor 
    extends InstantiationAwareBeanPostProcessorAdapter
    implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware
  • InstantiationAwareBeanPostProcessorAdapter能夠設(shè)置Bean的屬性值
  • PriorityOrdered接口用于標(biāo)識(shí)這個(gè)類的創(chuàng)建的優(yōu)先級(jí)
  • BeanFactoryAware接口用于獲取Spring的BeanFactory
  • MergedBeanDefinitionPostProcessor:合并Bean定義后置處理器(繼承BeanPostProcessor)

構(gòu)造函數(shù)

在創(chuàng)建的時(shí)候會(huì)把Autowired和Value設(shè)置到autowiredAnnotationTypes這個(gè)列表中寿烟,如果存在@Inject這個(gè)注解也同樣會(huì)被塞進(jìn)去

  private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>();
  
  public AutowiredAnnotationBeanPostProcessor() {
        this.autowiredAnnotationTypes.add(Autowired.class);
        this.autowiredAnnotationTypes.add(Value.class);
        try {
            this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                    ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
            logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
        }
        catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }

運(yùn)行過程

在容器執(zhí)行的時(shí)候會(huì)調(diào)用refresh()方法,里面有個(gè)registerBeanPostProcessor方法异吻,
會(huì)對(duì)AutowiredAnnotationBeanPostProcessor進(jìn)行一個(gè)注冊(cè)

之后會(huì)執(zhí)行finishBeanFactoryInitialization(beanFactory)方法對(duì)非延遲初始化的單例bean進(jìn)行初始化時(shí)唱凯,
會(huì)執(zhí)行到AbstractAutowireCapableBeanFactory的createBean方法桨仿,并且調(diào)用doCreateBean方法創(chuàng)建Bean睛低,
會(huì)調(diào)用MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition方法

    /**
     * 這個(gè)方法是對(duì)注入屬性的創(chuàng)建
     */
    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof MergedBeanDefinitionPostProcessor) {
                MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
            }
        }
    }
    
    // 在此之后會(huì)調(diào)用populateBean這個(gè)方法
    // 在postProcessPropertyValues中才是最后把屬性給寫出去
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvs == null) {
                return;
            }
        }
    }
    
    

所以說,我們需要從postProcessMergedBeanDefinition這個(gè)方法開始看起

首先先定義了三個(gè)測(cè)試類:


   @RestController
   public class DemoController {
       @Autowired
       private DemoService demoService;
   
       @RequestMapping("/")
       String home() {
           return demoService.getString();
       }
   }
   
   @Service
   public class DemoService {
   
       public String getString() {
           return "Hello World!";
       }
   }
   @SpringBootApplication
   public class SampleController {
   
   
       public static void main(String[] args) throws Exception {
           SpringApplication.run(SampleController.class, args);
       }
   }
   

在啟動(dòng)的時(shí)候,Spring會(huì)尋找每個(gè)Bean钱雷,并且調(diào)用postProcessMergedBeanDefinition為他們注入還有@Autowire的屬性

[圖片上傳失敗...(image-e85ff9-1530195131381)]

這里算是預(yù)處理部分骂铁,將注入列表給弄出來

/**
 * 最終緩存列表的地方
 */
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
    Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
    for (InjectedElement element : this.injectedElements) {
        Member member = element.getMember();
        if (!beanDefinition.isExternallyManagedConfigMember(member)) {
            beanDefinition.registerExternallyManagedConfigMember(member);
            checkedElements.add(element);
            if (logger.isDebugEnabled()) {
                logger.debug("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
            }
        }
    }
    this.checkedElements = checkedElements;
}

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // 接下來的操作會(huì)鎖資源,所以先進(jìn)行一遍查找罩抗,如果查詢出來的沒有被處理過才進(jìn)行處理
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                // 構(gòu)造需要注入的元素
                metadata = buildAutowiringMetadata(clazz);
                // 將處理過的給緩存起來
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}
public static boolean needsRefresh(@Nullable InjectionMetadata metadata, Class<?> clazz) {
    return (metadata == null || metadata.targetClass != clazz);
}

    
/**
* 構(gòu)造需要注入的元素
*
*/
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
    Class<?> targetClass = clazz;
    do {
        final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
        // 循環(huán)這個(gè)類的所有屬性
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            // 尋找含有在autowiredAnnotationTypes注解列表里面的屬性
            AnnotationAttributes ann = findAutowiredAnnotation(field);
            // 如果不為空書面還有
            if (ann != null) {
                // 屬性的修飾符不能是靜態(tài)的
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                // 校驗(yàn)一下權(quán)限
                boolean required = determineRequiredStatus(ann);
                // 當(dāng)前的屬性表加入一個(gè)新的需要注入的屬性
                // 其實(shí)就是把DemoService放到這個(gè)列表中作為備用
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });
        // 這段就是尋找還有包含自動(dòng)注入的方法
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
            if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                if (Modifier.isStatic(method.getModifiers())) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Autowired annotation is not supported on static methods: " + method);
                    }
                    return;
                }
                if (method.getParameterCount() == 0) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Autowired annotation should only be used on methods with parameters: " +
                                method);
                    }
                }
                boolean required = determineRequiredStatus(ann);
                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                currElements.add(new AutowiredMethodElement(method, required, pd));
            }
        });

        elements.addAll(0, currElements);
        // 類似遞歸去尋找他父類的注入信息
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);
    // 最后返回一個(gè)這個(gè)類需要注入的列表出去
    return new InjectionMetadata(clazz, elements);
}

最后將屬性注入到Bean中

    @Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
        // 由于在上一步就已經(jīng)進(jìn)行了創(chuàng)建所以這不會(huì)再進(jìn)行創(chuàng)建拉庵,直接把列表返回
        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;
    }
    
    public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection<InjectedElement> checkedElements = this.checkedElements;
        // 要注入的屬性列表
        Collection<InjectedElement> elementsToIterate =
                (checkedElements != null ? checkedElements : this.injectedElements);
        if (!elementsToIterate.isEmpty()) {
            boolean debug = logger.isDebugEnabled();
            // 依次注入各個(gè)屬性
            for (InjectedElement element : elementsToIterate) {
                if (debug) {
                    logger.debug("Processing injected element of bean '" + beanName + "': " + element);
                }
                element.inject(target, beanName, pvs);
            }
        }
    }
    
    @Override
    protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        // 獲取成員屬性
        Field field = (Field) this.member;
        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;
                }
            }
        }
        // 上面都是執(zhí)行各種構(gòu)造,最終是使用反射將值塞到對(duì)應(yīng)的Bean里面
        if (value != null) {
            ReflectionUtils.makeAccessible(field);
            field.set(bean, value);
        }
    }

[圖片上傳失敗...(image-d50582-1530195131381)]

END

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末套蒂,一起剝皮案震驚了整個(gè)濱河市钞支,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌操刀,老刑警劉巖烁挟,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異馍刮,居然都是意外死亡信夫,警方通過查閱死者的電腦和手機(jī)窃蹋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門卡啰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人警没,你說我怎么就攤上這事匈辱。” “怎么了杀迹?”我有些...
    開封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵亡脸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我树酪,道長(zhǎng)浅碾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任续语,我火速辦了婚禮垂谢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疮茄。我一直安慰自己滥朱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開白布力试。 她就那樣靜靜地躺著徙邻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪畸裳。 梳的紋絲不亂的頭發(fā)上缰犁,一...
    開封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼帅容。 笑死薇芝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的丰嘉。 我是一名探鬼主播夯到,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼饮亏!你這毒婦竟也來了耍贾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤路幸,失蹤者是張志新(化名)和其女友劉穎荐开,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體简肴,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晃听,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了砰识。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片能扒。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖辫狼,靈堂內(nèi)的尸體忽然破棺而出初斑,到底是詐尸還是另有隱情,我是刑警寧澤膨处,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布见秤,位于F島的核電站,受9級(jí)特大地震影響真椿,放射性物質(zhì)發(fā)生泄漏鹃答。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一突硝、第九天 我趴在偏房一處隱蔽的房頂上張望测摔。 院中可真熱鬧,春花似錦狞换、人聲如沸避咆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)查库。三九已至,卻和暖如春黄琼,著一層夾襖步出監(jiān)牢的瞬間樊销,已是汗流浹背整慎。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留围苫,地道東北人裤园。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像剂府,于是被迫代替她去往敵國(guó)和親拧揽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354