亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

追蹤解析Spring ioc啟動(dòng)源碼(2)

funnyZhang / 1880人閱讀

摘要:顧名思義,其主要作用是解析標(biāo)簽。本例中沒(méi)有用到上述的注解,所以均為。繼續(xù)追蹤這行代碼的內(nèi)部實(shí)現(xiàn)獲取的名稱(chēng)調(diào)用的方法注冊(cè)過(guò)程見(jiàn)處理的別名,本例中沒(méi)有別名,不進(jìn)入循環(huán)的具體內(nèi)容有待研究,不展開(kāi)。到此為止,已經(jīng)被注冊(cè)到中。

接上篇 3 reader 注冊(cè)配置類(lèi)

該 part 的起點(diǎn):

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
    this();    
    register(annotatedClasses);        // 3 reader 注冊(cè)配置類(lèi)
    refresh();
}

該行代碼會(huì)將 iocConfig bean 注冊(cè)到 reader 中
AnnotationConfigApplicationContext 的 register 方法:

//AnnotationConfigApplicationContext.class
public void register(Class... annotatedClasses) {
    //參數(shù)非空效驗(yàn)
    Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); 
    //調(diào)用 AnnotatedBeanDefinitionReader 的 register 方法
    this.reader.register(annotatedClasses); 
}

上述方法主要是調(diào)用了 AnnotatedBeanDefinitionReader 的 register 方法:

//AnnotatedBeanDefinitionReader.class
public void register(Class... annotatedClasses) {
    for (Class annotatedClass : annotatedClasses) {
        registerBean(annotatedClass);
    }
}

上述方法循環(huán)調(diào)用了 AnnotatedBeanDefinitionReader 的 registerBean 方法:

//AnnotatedBeanDefinitionReader.class
public void registerBean(Class annotatedClass) {
    doRegisterBean(annotatedClass, null, null, null);
}

上述方法調(diào)用了 AnnotatedBeanDefinitionReader 的 doRegisterBean 方法,這個(gè)方法比較長(zhǎng),需要重點(diǎn)關(guān)注:

//AnnotatedBeanDefinitionReader.class
 void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
        @Nullable Class[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

    //用 BeanDefinition 包裝 iocConfig
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); 
    
    //此段代碼用于處理 Conditional 注解,在特定條件下阻斷 bean 的注冊(cè)
    //本例中此處不會(huì) return
    //3.1
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { 
        return;
    }

    //用來(lái)創(chuàng)建 bean 的 supplier,會(huì)替代掉 bean 本身的創(chuàng)建方法
    //instanceSupplier 一般情況下為 null
    abd.setInstanceSupplier(instanceSupplier); 

    //此行代碼處理 scope 注解,本例中 scope 是默認(rèn)值 singleton
    //3.2
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName()); 

    //bean name 在本例中為自動(dòng)生成的 iocConfig
    //3.3
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); 

    //特定注解解析,本例中均不做操作
    //3.4
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); 

    //本例中 qualifiers 傳入的是 null
    //3.5
    if (qualifiers != null) { 
        for (Class qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }

    //本例中 definitionCustomizers 傳入的是 null
    //3.6
    for (BeanDefinitionCustomizer customizer : definitionCustomizers) { 
        customizer.customize(abd);
    }

    //用 BeanDefinitionHolder 包裝 BeanDefinition
    BeanDefinitionHolder definitionHolder 
        = new BeanDefinitionHolder(abd,beanName); 
    
    //此行代碼與動(dòng)態(tài)代理和 scope 注解有關(guān),但是在本案例中沒(méi)有做任何操作,只是返回了傳入的 definitionHolder
    //3.7
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); 

    //iocConfig 注冊(cè)
    // 3.8
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry); 
}
3.1

看一下上述方法的片段:

if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) { 
    return;
}

首先需要了解到 abd 的 getMetadata() 方法會(huì)獲取到 abd 中的 metadata 對(duì)象。

該對(duì)象是一個(gè) StandardAnnotationMetadata 的實(shí)例化對(duì)象,在創(chuàng)建的時(shí)候會(huì)利用 java.Class 中的 api 獲取 bean 中所有的注解,并保存為一個(gè)數(shù)組:

//StandardAnnotationMetadata.class
public StandardAnnotationMetadata(Class introspectedClass, boolean nestedAnnotationsAsMap) {
    //此處的 introspectedClass 即為 bean 的 class
    //父類(lèi)的構(gòu)造器用于內(nèi)部保存 bean 的 class
    super(introspectedClass);
    //獲取所有的注解
    this.annotations = introspectedClass.getAnnotations();
    //nestedAnnotationsAsMap 暫時(shí)用不上,按下不表
    //nestedAnnotationsAsMap = true
    this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
}

conditionEvaluator 是一個(gè)注解解析器,在 AnnotatedBeanDefinitionReader 創(chuàng)建的時(shí)候在其構(gòu)造方法內(nèi)被創(chuàng)建:

this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);

追蹤 conditionEvaluator 的 shouldSkip(...) 方法:

//ConditionEvaluator.class
public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
    return shouldSkip(metadata, null); //調(diào)用自身的重載方法
}

//ConditionEvaluator.class
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
    //metadata 在此處不為 null
    //判斷 bean 是否使用了 Conditional 注解
    if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
        //如果 metadata為空或者 bean 沒(méi)有使用 Conditional 注解,就會(huì)返回 false
        return false; 
    }

    //第一次調(diào)用該方法的時(shí)候,phase 為 null
    if (phase == null) {
        //下列源碼規(guī)整一下,其實(shí)是四個(gè)條件:
        //1 bean.metadata 是 AnnotationMetadata 或其子類(lèi)
        //2 bean 使用了 Configuration 注解
        //3 bean 不是一個(gè)接口
        //4 bean 使用了 Component、ComponentScan、Import、ImportResource 這四個(gè)注解之一,或者使用了 Bean 注解
        //這四個(gè)條件中滿(mǎn)足 1、2 或者 1、3、4 就會(huì)進(jìn)入 if 語(yǔ)句中
        //請(qǐng)注意,對(duì)于 config bean 來(lái)說(shuō),只要使用了 Conditional 注解,必然會(huì)進(jìn)入到語(yǔ)句中
        if (metadata instanceof AnnotationMetadata &&
                ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
            return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
        }
        return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
    }

    List conditions = new ArrayList<>();
    //getConditionClasses(metadata) 會(huì)獲取到 Conditional 注解中的 value 數(shù)組
    for (String[] conditionClasses : getConditionClasses(metadata)) {
        //遍歷數(shù)組
        for (String conditionClass : conditionClasses) {
            //利用反射獲取實(shí)例化數(shù)組內(nèi)的 class
            Condition condition = getCondition(conditionClass, this.context.getClassLoader());
            conditions.add(condition); //獲取所有的 canditionClass 并以次存入到列表中
        }
    }

    //利用了 List 自帶的排序 api 進(jìn)行排序
    AnnotationAwareOrderComparator.sort(conditions);

    for (Condition condition : conditions) {
        ConfigurationPhase requiredPhase = null;
        if (condition instanceof ConfigurationCondition) {
            requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
        }

        //對(duì)于 Conditional 內(nèi)的 value 并非是實(shí)現(xiàn) ConfigurationCondition 接口的 class,requiredPhase == null 必然為 true;對(duì)于實(shí)現(xiàn)了該接口的 class,requiredPhase == phase 必然為 true
        //所以要注意,如果 value class 的 matches(...) 方法返回 false,則會(huì)在此處阻斷 bean 的注冊(cè)
        if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
            return true;
        }
    }

    //正常情況下,做完所有檢查工作之后還是會(huì)返回 false
    return false;
}

可以看到這個(gè)方法其實(shí)是 Conditional 注解的解析器,對(duì)于未使用這個(gè)注解的 bean,直接就返回了,不會(huì)繼續(xù)往下走。

先來(lái)看一下 Conditional 的源碼:

@Target({ElementType.TYPE, ElementType.METHOD}) //可以標(biāo)注在類(lèi)和方法上方
@Retention(RetentionPolicy.RUNTIME) //注解生命周期
@Documented //javadoc 相關(guān)
public @interface Conditional {
    //class 數(shù)組
    //這個(gè)數(shù)組里的值必須要是實(shí)現(xiàn)了 Condition 接口的類(lèi)
    //注意這個(gè) value 沒(méi)有默認(rèn)值,如果要使用該注解就必須要填入
    Class[] value();
}

順便來(lái)看一下 Condition 接口:

public interface Condition {

    //這個(gè)方法會(huì)返回一個(gè) boolean 值,如果為 true,則將繼承該接口的類(lèi)注入到 Conditional 修飾的 bean 中
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

conditional 的具體內(nèi)容有待研究,不展開(kāi)。

3.2

看下方代碼片段:

ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName()); 

scopeMetadataResolver 是一個(gè)定義在 AnnotatedBeanDefinitionReader 里的 AnnotationScopeMetadataResolver 對(duì)象。顧名思義,其主要作用是解析 scope 標(biāo)簽。

先來(lái)看一下 Scope 注解的定義源碼:

@Target({ElementType.TYPE, ElementType.METHOD}) //可以標(biāo)注在類(lèi)和方法上方
@Retention(RetentionPolicy.RUNTIME) //注解生命周期
@Documented //javadoc 相關(guān)
public @interface Scope {

    //value 是平時(shí)開(kāi)發(fā)中最常用到的 scope 屬性,用來(lái)設(shè)置是否是單例模式
    //在處理注解的時(shí)候 value 屬性會(huì)被轉(zhuǎn)化成 scopeName 屬性來(lái)看待
    //所以?xún)蓚€(gè)屬性其實(shí)是一樣的
    String value() default "";
    String scopeName() default "";
    //代理模式設(shè)置,默認(rèn)為無(wú)代理
    ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}

ScopedProxyMode 是一個(gè)枚舉類(lèi),沒(méi)有任何處理業(yè)務(wù)邏輯的代碼,一同放在這里:

public enum ScopedProxyMode {
    DEFAULT,        //不使用代理,default 和 no 是等價(jià)的
    NO,
    INTERFACES,        //使用 jdk 自帶的動(dòng)態(tài)代理 api 進(jìn)行創(chuàng)建
    TARGET_CLASS;    //target-class 模式,需要使用 cglib 進(jìn)行 bean 的創(chuàng)建
 }

AnnotationScopeMetadataResolver 的 resolveScopeMetadata(...) 方法具體實(shí)現(xiàn)如下:

//AnnotationScopeMetadataResolver.class
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
    //創(chuàng)建一個(gè) metadata 對(duì)象用于返回
    ScopeMetadata metadata = new ScopeMetadata();

    if (definition instanceof AnnotatedBeanDefinition) {
        AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
        //從 bean 的注解里尋找 scope 這個(gè)注解
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
                annDef.getMetadata(), this.scopeAnnotationType);

        //如果 bean 確實(shí)是用了 scope 注解
        if (attributes != null) {
            metadata.setScopeName(attributes.getString("value")); //存入 scope 的 value 屬性值
            //獲取 proxyMode 屬性值
            ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
            //default 和 no 是等同的,默認(rèn)會(huì)轉(zhuǎn)化成 no 進(jìn)行處理
            if (proxyMode == ScopedProxyMode.DEFAULT) {
                //this.defaultProxyMode = ScopedProxyMode.NO
                proxyMode = this.defaultProxyMode;
            }
            metadata.setScopedProxyMode(proxyMode); //存入 scope 的 proxyMode 屬性值
        }
    }
    //沒(méi)有使用 scope 的情況下會(huì)返回一個(gè)新建的 metadata
    return metadata;
}

annDef.getMetadata() 會(huì)獲取到一個(gè) AnnotationMetadata 對(duì)象,里面包含了 bean 的所有注解信息。

scopeAnnotationType 是一個(gè)定義在 AnnotationScopeMetadataResolver 里的 Class 對(duì)象:

protected Class scopeAnnotationType = Scope.class;

可見(jiàn) AnnotationConfigUtils 的 attributesFor(...) 就是去注解集里查找 scope 注解,并且封裝成一個(gè) AnnotationAttributes 返回。
AnnotationAttributes 是 Spring 用來(lái)存儲(chǔ)注解所定義的一種數(shù)據(jù)結(jié)構(gòu),本質(zhì)上是一個(gè) LinkedHashMap。

再回到本小節(jié)最上方的代碼:

abd.setScope(scopeMetadata.getScopeName()); 

最后其實(shí) BeanDefinition 只接收了 scopeName,而沒(méi)有接收 proxyMode。proxyMode 屬性會(huì)在后面代碼中用到。

3.3

看下方代碼片段:

String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); 

beanNameGenerator 是一個(gè)定義在 AnnotatedBeanDefinitionReader 里的 AnnotationBeanNameGenerator 對(duì)象,顧名思義用來(lái)生成 bean 的名稱(chēng):

private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();

追蹤一下 generateBeanName(...) 方法:

//AnnotationBeanNameGenerator.class
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    
    if (definition instanceof AnnotatedBeanDefinition) {
        //determineBeanNameFromAnnotation(...) 方法會(huì)從 bean 的所有注解里去遍歷搜尋 bean 名稱(chēng)
        String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
        //如果此處的 beanName 非空,則表明在注解里找到了定義的 bean 名稱(chēng)
        if (StringUtils.hasText(beanName)) {
            // Explicit bean name found.
            return beanName;
        }
    }
    //沒(méi)有在前面 return,證明 bean 沒(méi)有被設(shè)置名稱(chēng),則在此處默認(rèn)生成一個(gè)名稱(chēng)
    return buildDefaultBeanName(definition, registry);
}

看一眼 buildDefaultBeanName(...) 方法:

//AnnotationBeanNameGenerator.class
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    return buildDefaultBeanName(definition);
}

其實(shí)這個(gè)方法只用到了 definition,而沒(méi)有使用到傳入的 registry。

繼續(xù)追蹤代碼實(shí)現(xiàn):

//AnnotationBeanNameGenerator.class
protected String buildDefaultBeanName(BeanDefinition definition) {
    //該處返回的是 bean 的整個(gè) class 路徑和名稱(chēng)
    String beanClassName = definition.getBeanClassName();
    //beanClassName 非空判斷
    Assert.state(beanClassName != null, "No bean class name set");
    //截掉 class 的路徑,只取 class 名稱(chēng)
    String shortClassName = ClassUtils.getShortName(beanClassName);
    //將首字母小寫(xiě)并返回
    return Introspector.decapitalize(shortClassName);
}
3.4

看下方代碼實(shí)現(xiàn):

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); 

追蹤這行代碼:

//AnnotationConfigUtils.class
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    //調(diào)用重載方法
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
}

//AnnotationConfigUtils.class
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    //檢查 lazy 注解
    AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
    if (lazy != null) {
        abd.setLazyInit(lazy.getBoolean("value"));
    }else if (abd.getMetadata() != metadata) {
        //這里還有一個(gè)補(bǔ)充檢查,如果傳入的 metadata 不是 abd 內(nèi)部的 metadata的話,還會(huì)繼續(xù)進(jìn)來(lái)判斷一次
        //在本例中沒(méi)什么必要
        lazy = attributesFor(abd.getMetadata(), Lazy.class);
        if (lazy != null) {
            abd.setLazyInit(lazy.getBoolean("value"));
        }
    }

    //檢查 primary 注解
    if (metadata.isAnnotated(Primary.class.getName())) {
        abd.setPrimary(true);
    }

    //檢查 dependsOn 注解
    AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
    if (dependsOn != null) {
        abd.setDependsOn(dependsOn.getStringArray("value"));
    }

    //檢查 role 注解
    AnnotationAttributes role = attributesFor(metadata, Role.class);
    if (role != null) {
        abd.setRole(role.getNumber("value").intValue());
    }

    //檢查 description 注解
    AnnotationAttributes description = attributesFor(metadata, Description.class);
    if (description != null) {
        abd.setDescription(description.getString("value"));
    }
}

其實(shí)上述代碼的主體都是類(lèi)似的,步驟都是嘗試從 metadata 中獲取特定注解,如果獲取到了就將其作為一個(gè)屬性值 set 進(jìn) abd 中。

這里需要強(qiáng)調(diào) abd 就是要注冊(cè)的 bean 的 BeanDefinition 包裝對(duì)象。

本例中沒(méi)有用到上述的注解,所以均為 null。

3.5

看下方代碼:

if (qualifiers != null) {
    //在 qualifiers 不為 null 的情況下會(huì)遍歷該集合,并將當(dāng)中的所有的元素解析出來(lái),進(jìn)行業(yè)務(wù)操作
    for (Class qualifier : qualifiers) {
        if (Primary.class == qualifier) {
            abd.setPrimary(true);
        }else if (Lazy.class == qualifier) {
            abd.setLazyInit(true);
        }else {
            abd.addQualifier(new AutowireCandidateQualifier(qualifier));
        }
    }
}

上述代碼是針對(duì) qualifier 注解的解析,和 3.4 很類(lèi)似。

AutowireCandidateQualifier 是注解的包裝類(lèi),儲(chǔ)存了一個(gè)特定注解的名字和 value。abd 的 addQualifier(...) 方法會(huì)將這個(gè)創(chuàng)建出來(lái)的包裝類(lèi)存儲(chǔ)到一個(gè) map 對(duì)象里。

3.6

看下方代碼:

for (BeanDefinitionCustomizer customizer : definitionCustomizers) { 
    customizer.customize(abd);
}

這段代碼是 Spring5 中新加入的。根據(jù)注釋?zhuān)俜綉?yīng)該是留下這個(gè)接口用以讓開(kāi)發(fā)者通過(guò) lambda 表達(dá)式去定義 bean。

3.7

看下方代碼:

definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); 

先來(lái)追蹤 applyScopedProxyMode(...) 方法:

//AnnotationConfigUtils.class
static BeanDefinitionHolder applyScopedProxyMode(
            ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
    //先判斷 scope 注解的使用
    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
        return definition;
    }
    //判斷具體使用哪種模式
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
    //此行代碼會(huì)連向 spring-aop 包下的類(lèi)來(lái)處理
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}

注意,此處傳入的 metadata 是上述 3.2 小節(jié)中新建出來(lái)并返回的對(duì)象:

ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);

對(duì)于一般沒(méi)有使用 scope 注解或者 scope 注解為默認(rèn)的 bean,此時(shí) scopedProxyMode 是等于 ScopedProxyMode.NO 的。

對(duì)于 scopedProxyMode 不為 NO 的 bean,均為需要使用動(dòng)態(tài)代理進(jìn)行創(chuàng)建的對(duì)象,區(qū)別只是使用 jdk 自帶的 api 還是使用 cglib 包。

追蹤一下 ScopedProxyCreator 的 createScopedProxy(...) 方法:

//ScopedProxyCreator.class
public static BeanDefinitionHolder createScopedProxy(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
    return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}

繼續(xù)追蹤:

//ScopedProxyUtils.class
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
            BeanDefinitionRegistry registry, boolean proxyTargetClass) {
    //bean 的名稱(chēng)
    String originalBeanName = definition.getBeanName();
    //bean 的 BeanDefinition 包裝類(lèi)
    BeanDefinition targetDefinition = definition.getBeanDefinition();
    //在 bean 的名稱(chēng)前面加上字符串 "scopedTarget." ,拼成 targetBeanName
    //比如 scopedTarget.iocConfig
    String targetBeanName = getTargetBeanName(originalBeanName);

    //以下代碼用來(lái)組裝一個(gè)動(dòng)態(tài)代理的工廠 bean,這個(gè) bean 是用來(lái)動(dòng)態(tài)代理的主體
    RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
    proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
    proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
    proxyDefinition.setSource(definition.getSource());
    proxyDefinition.setRole(targetDefinition.getRole());

    proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
    if (proxyTargetClass) {
        targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
    }else {
        proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
    }
    proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
    proxyDefinition.setPrimary(targetDefinition.isPrimary());
    if (targetDefinition instanceof AbstractBeanDefinition) {
        proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
    }
    targetDefinition.setAutowireCandidate(false);
    targetDefinition.setPrimary(false);

    //此處的 targetDefinition 是傳入的 bean 的包裝類(lèi)
    //這一步會(huì)提前將該 bean 進(jìn)行注冊(cè)
    //注冊(cè)過(guò)程見(jiàn) 2.2
    registry.registerBeanDefinition(targetBeanName, targetDefinition);

    //返回的其實(shí)是動(dòng)態(tài)代理所需要的工廠 bean
    return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}

scope 的具體內(nèi)容有待研究,不展開(kāi)。

3.8

在上例代碼中的這一行中:

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

傳入的 definitionHolder 就是 iocConfig bean 的包裝對(duì)象;而傳入的 registry 就是在 ApplicationContext 中實(shí)例化的 BeanFactory,此處具體而言就是DefaultListableBeanFactory。

繼續(xù)追蹤這行代碼的內(nèi)部實(shí)現(xiàn):

//BeanDefinitionReaderUtils.class
public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {

    //獲取bean的名稱(chēng)
    String beanName = definitionHolder.getBeanName();

    //調(diào)用 AnnotationConfigApplicationContext 的 registerBeanDefinition 方法
    //注冊(cè)過(guò)程見(jiàn) 2.2
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    //處理bean的別名,本例中沒(méi)有別名,不進(jìn)入循環(huán)
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

alias 的具體內(nèi)容有待研究,不展開(kāi)。

到此為止,iocConfig bean 已經(jīng)被注冊(cè)到 bean factory 中。

To Be Continued ...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/72747.html

相關(guān)文章

  • 追蹤解析Spring ioc啟動(dòng)源碼(1)

    摘要:主要過(guò)程為調(diào)用自身的另一個(gè)有參構(gòu)造器此處的即為本身此處的最終返回一個(gè)調(diào)用無(wú)參構(gòu)造器創(chuàng)建出來(lái)的對(duì)象參數(shù)非空效驗(yàn)保存創(chuàng)建一個(gè)用于注解解析器,后面會(huì)用到注冊(cè)需要用到的顧名思義,即為所處的環(huán)境,包括配置的讀取等。 零 前期準(zhǔn)備 0 FBI WARNING 文章異常啰嗦且繞彎。 1 版本 spring版本 : spring 5.1.2.RELEASE IDE : idea 2018.3 2 Be...

    Cheng_Gang 評(píng)論0 收藏0
  • 重拾-Spring-IOC

    摘要:為何重拾使用了多年,但是對(duì)其底層的一些實(shí)現(xiàn)還是一知半解,一些概念比較模糊故決定重新拾起,加深對(duì)的認(rèn)識(shí)。小結(jié)是在完成創(chuàng)建后對(duì)其進(jìn)行后置處理的接口是在完成實(shí)例化對(duì)其進(jìn)行的后置處理接口是框架底層的核心接口,其提供了創(chuàng)建,獲取等核心功能。 為何重拾 使用了 Spring 多年,但是對(duì)其底層的一些實(shí)現(xiàn)還是一知半解,一些概念比較模糊;故決定重新拾起,加深對(duì) Spring 的認(rèn)識(shí)。 重拾計(jì)劃 spr...

    GraphQuery 評(píng)論0 收藏0
  • Spring AOP從零單排-織入時(shí)期源碼分析

    摘要:何為簡(jiǎn)單點(diǎn)來(lái)定義就是切面,是一種編程范式。定義一個(gè)切面的載體定義一個(gè)切點(diǎn)定義一個(gè)為,并指定對(duì)應(yīng)的切點(diǎn)一個(gè)注冊(cè)配置類(lèi),啟動(dòng)容器,初始化時(shí)期獲取對(duì)象,獲取對(duì)象時(shí)期,并進(jìn)行打印好了,這樣我們整體的代理就已經(jīng)完成。 問(wèn)題:Spring AOP代理中的運(yùn)行時(shí)期,是在初始化時(shí)期織入還是獲取對(duì)象時(shí)期織入? 織入就是代理的過(guò)程,指目標(biāo)對(duì)象進(jìn)行封裝轉(zhuǎn)換成代理,實(shí)現(xiàn)了代理,就可以運(yùn)用各種代理的場(chǎng)景模式。 ...

    honmaple 評(píng)論0 收藏0
  • Spring專(zhuān)題之IOC源碼分析

    摘要:前言以下源碼基于版本解析。實(shí)現(xiàn)源碼分析對(duì)于的實(shí)現(xiàn),總結(jié)來(lái)說(shuō)就是定位加載和注冊(cè)。定位就是需要定位配置文件的位置,加載就是將配置文件加載進(jìn)內(nèi)存注冊(cè)就是通過(guò)解析配置文件注冊(cè)。下面我們從其中的一種使用的方式一步一步的分析的實(shí)現(xiàn)源碼。 前言 以下源碼基于Spring 5.0.2版本解析。 什么是IOC容器? 容器,顧名思義可以用來(lái)容納一切事物。我們平常所說(shuō)的Spring IOC容器就是一個(gè)可以容...

    不知名網(wǎng)友 評(píng)論0 收藏0
  • SpringBoot 中 @SpringBootApplication注解背后的三體結(jié)構(gòu)探秘

    摘要:概述約定大于配置的功力讓我們?nèi)玢宕猴L(fēng),在我之前寫(xiě)的文章從到也對(duì)比過(guò)和這兩個(gè)框架,不過(guò)最終以超高的代碼信噪比和易上手性讓我們映像頗深。至于,我想在非時(shí)代大家應(yīng)該不陌生吧,作用是配置容器,也即形式的容器的配置類(lèi)所使用。 showImg(https://segmentfault.com/img/remote/1460000015822144); 概 述 SpringBoot 約定大于配置...

    Tecode 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<