成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring注解專題系列

CocoaChina / 2700人閱讀

摘要:用法先創(chuàng)建個組件,,,分別在類上加上注解。發(fā)現(xiàn)有一個屬性源碼注釋這樣說的自動檢測使用組件。在的方法中,表示不匹配,代表匹配。這就說明使用注冊組件有種方式。

Spring注解應(yīng)用篇--IOC容器Bean組件注冊
這是Spring注解專題系類文章,本系類文章適合Spring入門者或者原理入門者,小編會在本系類文章下進(jìn)行企業(yè)級應(yīng)用實戰(zhàn)講解以及spring源碼跟進(jìn)。
環(huán)境準(zhǔn)備

編譯器IDEA

maven依賴spring-context version:4.3.12.RELEASE

maven依賴junit version:4.11

Bean && Configuration注解

小編經(jīng)歷過xml文件配置的方式,后來使用springboot后發(fā)現(xiàn)開箱即用的零xml配置方式(除了框架外中間件等配置~)簡直不要太清爽。然后基于注解驅(qū)動開發(fā)的特性其實spring早就存在了()
Spring的特性包括IOC和DI(依賴注入)
傳統(tǒng)的xml Bean注入方式:

xml式Bean注入

或者注入Bean的同時進(jìn)行屬性注入




上面?zhèn)鹘y(tǒng)的代碼其實就是等價于:
配置類注冊Bean

@Configuration
public class BaseConfig {
    @Bean("beanIdDefinition")
    public ExampleBean exampleBean(){
        return new ExampleBean("evinhope",666);
    }
}

@ Configuration等價于xml配置文件,表示它是一個配置類,@ bean等價于xml的bean標(biāo)簽,告訴容器這個bean需要注冊到IOC容器當(dāng)中。幾乎xml的每一個標(biāo)簽或者標(biāo)簽屬性都可以對應(yīng)一個注解。其中使用bean注解時,默認(rèn)bean id為方法名(exampleBean),當(dāng)然也可以通過@ Bean(xxxx)來指定bean的id。
測試用例

@Test
    public void shouldAnswerWithTrue()
    {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BaseConfig.class);//創(chuàng)建IOC容器
        System.out.println("IOC容器創(chuàng)建完成...");
        ExampleBean exampleBean = (ExampleBean) ctx.getBean("beanIdDefinition");//獲取id為beanIDDefinition的Bean
        System.out.println(exampleBean);
    }

output:

IOC容器創(chuàng)建完成...
ExampleBean{name="evinhope", age=666}

創(chuàng)建IOC容器并且獲取后,與getBean相關(guān)的方法:

這一些IOC容器方法后續(xù)在其他注解證明上可能會用得上,這里挑幾個說明一下:
getBeanNamesForType(bean.class),根據(jù)bean的類型返回此類型bean的所有id(ret String[])
getBeanDefinitionNames(),獲取容器中定義的所有bean id(ret String[])
output:

[beanIdDefinition, exampleBean02]  [IOC容器在創(chuàng)建過程中往里面注冊的bean, baseConfig, beanIdDefinition, exampleBean02]
//其中beanIdDefinition和exampleBean02為同類型的bean,不同id;baseConfig為配置類~

@ Configuration源碼點進(jìn)去,這個注釋上還有@ Component注釋,說明配置類注釋其實也是一個組件bean

componentScan注解自動掃描組件&指定掃描規(guī)則

這個注解等價于xml的content:component-scan標(biāo)簽
componentScan注解包掃描,只要標(biāo)注了@Controller、@Service、@Repository、@component四大注解的都會自動掃描加入到IOC中。
注解解讀
注釋源碼點進(jìn)去后可以看到包含一個@Repeatable注解,跟著點進(jìn)去,可以得知Repeatable始于JDK1.8,表示其聲明的注釋類型,說明@componentScan可以重復(fù)使用,來掃描多個包路徑。
這里關(guān)注幾個有意思的注解屬性:
value/basePackages:在xxxx包路徑下掃描組件
includeFilters:指定掃描的時候包含符合規(guī)則的組件(類型聲明為Filter[])
excludeFilters:指定哪些類型不符合組件掃描的條件(類型聲明為Filter[])
在來看Filter的定義信息:
Filter為componentScan注解下的嵌套注解。包含幾個重要的屬性:
FilterType type(默認(rèn)為FilterType.ANNOTATION):使用過濾的類型
其中FilterType為枚舉類,包含以下值:ANNOTATION(按照注解類型過濾組件)ASSIGNABLE_TYPE(按照主鍵類型過濾組件)ASPECTJ(按照切面表達(dá)式)REGEX(按照正則表達(dá)式)CUSTOM(自定義)
classes:定義完過濾類型后需要針對過濾類型來解釋過濾的類
pattern:用于過濾器的模式,主要和FilterType為按照切面表達(dá)式和按照正則表達(dá)式來組合使用。
用法:
先創(chuàng)建3個bean 組件,ControllerBean,ServiceBean,DaoBean(分別在類上加上@Controller、@Service、@Repository注解)。
測試前先用ApplicationContext的getBeanDefinitionNames()方法查看可知ioc中的確不存在上面3個bean組件。

@Configuration
@ComponentScan(value= "cn.edu.scau")
public class BaseConfig {

使用ApplicationContext的getBeanDefinitionNames()方法打印后,發(fā)現(xiàn)3個bean組件已經(jīng)加進(jìn)來容器中了,其中,bean id為首字母小寫的類名(controllerBean, daoBean, serviceBean)
進(jìn)行FilterType的使用。

@ComponentScan(value= "cn.edu.xxx",includeFilters = {
        @ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {Controller.class})
        })

按照上面的說明,此時容器應(yīng)該只有controller組件,service和dao應(yīng)該不在容器中,然而事實卻是3種組件都在容器中,這個源碼中說的不一樣???再回過頭看componentScan源碼。
發(fā)現(xiàn)有一個屬性boolean useDefaultFilters() default true源碼注釋這樣說的:自動檢測使用@controller@service@component@repository組件。然后上面的代碼再修改一下

@ComponentScan(value= "cn.edu.scau",includeFilters = {
        @ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {Controller.class}),
},useDefaultFilters = false)

再使用getBeanDefinitionNames查看容器bean,發(fā)現(xiàn)只剩下了controller注解標(biāo)注的bean,過濾成功。
由上面說明可知,includeFilter為Filter數(shù)組,則可定義多個過濾規(guī)則

@ComponentScan(value= "cn.edu.scau",includeFilters = {
        @ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {Controller.class}),
        @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes = {ServiceBean.class})
},useDefaultFilters = false)

結(jié)果就是容器中新增類型為ServiceBean的組件。
excludeFilters用法同includeFilters一樣,只不過它是過濾掉不符合條件的bean,同時需要搭配userDefaultFilters=false來使用
下面來試試FilterType為自定義的用法:
點進(jìn)去FilterType源碼后發(fā)現(xiàn)CUSTOM上面有注解{@link org.springframework.core.type.filter.TypeFilter} implementation.
這說明自定義規(guī)則需要實現(xiàn)TypeFilter接口
再來看看TypeFilter源碼:
接口定義了一個match方法:該方法用于確定包掃描下的類是否匹配
其中帶有2個參數(shù)以及返回類型:
@ Param(MetadataReader):當(dāng)前目標(biāo)類讀取信息
@ Param (MetadataReaderFactory):這個一個類信息讀取器工廠,可以獲取其他類信息
@ Return(boolean):返回當(dāng)前類是否符合過濾的要求

public class MyFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        return false;
    }
}
/*
* 同時在配置類中配置
*/
@ComponentScan(value= {"cn.edu.scau.controller","cn.edu.scau.service","cn.edu.scau.dao"},includeFilters = {
        @ComponentScan.Filter(type=FilterType.CUSTOM,classes = {MyFilter.class})
},useDefaultFilters = false)

在測試類中使用ApplicationContext的getBeanDefinitionNames方法發(fā)現(xiàn)controller、service、dao三個組件全部不在容器中或者調(diào)用Application的getBeanDefinitionCount方法發(fā)現(xiàn)比之前的少了3個bean。證明重寫TypeFilter 接口的match方法起作用了,false代表全部不匹配。
源碼點進(jìn)去看看MetadataReader的屬性描述:
getResource():返回當(dāng)前類資源引用(類路徑)
getClassMetadata():獲取當(dāng)前類的類信息
getAnnotationMetadata():獲取當(dāng)前類的注解信息

//return false的邏輯替換成
Resource resource = metadataReader.getResource();
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        String className = classMetadata.getClassName();
        if(className.contains("Dao")){
            return true;
        } //只返回類型帶有Dao的類
        return false; //其他類一律過濾掉

同理,查看結(jié)果,容器中只存在dao的bean組件,另外2個都沒有在容器中出現(xiàn),完成包掃描的過濾。
當(dāng)需要多包路徑多掃描規(guī)則的時候,可以使用多個componentScan(jdk8 支持,帶有repeatable元注解)或者使用一個componentScans(源碼跟進(jìn)可知,其實就是一個componentScan數(shù)組)

Scope注解設(shè)置組件的作用域

這個注解相當(dāng)于xml配置文件下bean標(biāo)簽的scope屬性。
IOC容器的Bean都是單實例,證明測試一下:

/*
* 還是上面注冊的那個Bean(id為beanIdDefinition)
*/
@Test
    public void shouldAnswerWithTrue()
    {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BaseConfig.class);
        System.out.println("IOC容器創(chuàng)建完成...");
        System.out.println(ctx.getBean("beanIdDefinition") == ctx.getBean("beanIdDefinition"));
    }

結(jié)果為true。說明多次從容器中獲取的bean為同一個,即為單實例。
Scope源碼跟進(jìn)去可以看到屬性value的值可以為singleton、prototype、request、session。分別代表該注解下的bean為單實例(ioc容器啟動后會調(diào)用方法創(chuàng)建對象放到容器中,以后需要該對象就從容器中獲?。瑸槎鄬嵗ㄈ萜鲃?chuàng)建啟動時不會去調(diào)用方法創(chuàng)建對象放進(jìn)容器中,只有在需要該對象的時候才會去new一個新對象),request代表同一個請求創(chuàng)建一個實例,session同一個session創(chuàng)建一個實例。
同時在bean中增加一個無參構(gòu)造器

public ExampleBean(){
        System.out.println("exampleBean constructor......");
    }

測試再跑一次,output:
exampleBean constructor......
IOC容器創(chuàng)建完成...
這說明單實例bean在容器初始化創(chuàng)建的過程中已經(jīng)注冊了。
在配置類bean中添加@Scope("prototype")
再跑一次,output:
IOC容器創(chuàng)建完成...
exampleBean constructor......
exampleBean constructor......
false
也說明了多實例容器創(chuàng)建啟動時不會去調(diào)用方法創(chuàng)建對象放進(jìn)容器中,只有在需要該對象的時候才會去new一個新對象。

Lazy注解Bean懶加載

這個注解主要針對單實例bean來說的,上面說過,默認(rèn)在容器啟動就創(chuàng)建了對象,懶加載ioc啟動后不創(chuàng)建對象,第一次獲取bean的時候再來創(chuàng)建bean,并進(jìn)行初始化。
在添加懶加載后再測試output:
IOC容器創(chuàng)建完成...
exampleBean constructor......
true
說明對象還是同一個,只是bean的創(chuàng)建容器注冊往后挪了。

Conditional注解按照條件來注冊bean

代碼跟進(jìn)去,發(fā)現(xiàn)只有一個Condition屬性為一個Class數(shù)組。(所有的組件必須匹配才能被注冊)再condition點進(jìn)去
Condition是一個接口,需要被實現(xiàn),實現(xiàn)里面的matches方法用來判斷該組件是否條件匹配。
分析到此,思路幾乎清晰,條件匹配類:

public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //TODO 等一下進(jìn)行代碼填充
        return false;
    }
}

先創(chuàng)建一個Computer的Bean對象,然后在配置類中進(jìn)行容器注冊

    @Bean("window")
    @Conditional(MyCondition.class)
    public Computer window(){
        return new Computer();
    }
    @Bean("linux")
    @Conditional(MyCondition.class)
    public Computer linux(){
        return new Computer();
    }

測試跑起來后發(fā)現(xiàn),容器中沒有id為linux和window的bean對象。在Conditon的matches方法中,false表示不匹配,ture代表匹配。
現(xiàn)實開發(fā)中可能有這樣的需求,不同的環(huán)境注冊不同的bean。
因此,嘗試在Condition的matches方法中看看里面的參數(shù)代表啥意思.
@ Param ConditionContext:獲取條件上下文環(huán)境
@ Param AnnotatedTypeMetadata:注解信息讀取

Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        //獲取到bean定義的注冊類.BeanDefinitionRegistry可以用來判斷bean的注冊信息,也可以在容器中注冊bean,后續(xù)文章會分析這個類
        BeanDefinitionRegistry registry = context.getRegistry();
        if(property.contains("windows")){
            return false;
        }
        return true;

測試跑起來,小編的電腦系統(tǒng)為Windows 10,則2個computer bean全部沒被注冊。
Junit測試可以調(diào)整改變JVM的參數(shù),步驟如下:
1、IDE找到Edit Configurations
2、在configuration這里找到VM options,這里可以設(shè)置JVM參數(shù)。這里我們改變運行的環(huán)境,改成linux.。寫法:-Dos.name=linux
測試再跑起來,2個bean又被注冊到容器中了。
可以在測試類獲取容器后再拿到環(huán)境確認(rèn)環(huán)境已經(jīng)改變了

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(BaseConfig.class);
        ConfigurableEnvironment environment = ctx.getEnvironment();
        String property = environment.getProperty("os.name");
        System.out.println(property);
        System.out.println("IOC容器創(chuàng)建完成...");

ouput:linux
回到Conditional注解的源碼的元注解:@Target({ElementType.TYPE, ElementType.METHOD})。Conditional這個注解可以用于方法和配置類上面,可以延伸如@Conditional注解放在配置上,若不符合條件,那么配置類下的所有bean都不會注冊到IOC容器中。
現(xiàn)實開發(fā)場景可以這個判斷條件需要大量使用,在每一個Bean上都寫上@Conditional(MyCondition.class)不太方便和比較繁瑣,因此可以嘗試把他再封裝一層,代碼看起來更加清爽:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(MyCondition.class)
public @interface MyDefinitionConditional {

}

這樣一來,凡是需要使用@Conditional(MyCondition.class)的地方都可以用@MyDefinitionConditional來代替。

Profile注解環(huán)境切換

在文檔中是這樣描述這個注解的:@Profile注解事實上是由一個更加靈活的@Conditional注解來實現(xiàn)了。
由源碼切入@Profile,發(fā)現(xiàn)此注解上還有@Conditional注解,@Conditional(ProfileCondition.class),ProfileCondition跟進(jìn)去,發(fā)現(xiàn)實現(xiàn)了Condition這個接口(和上面講的@Conditional一樣),下面為源碼中重寫了Condition的matches方法:

@Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        if (context.getEnvironment() != null) {
            MultiValueMap attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
            if (attrs != null) {
                for (Object value : attrs.get("value")) {
                    if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
                        return true;
                    }
                }
                return false;
            }
        }
        return true;
    }

這段代碼先通過上下文環(huán)境獲取所有帶有Profile注解的類方法信息,存在Profile注解的話,就會遍歷MultiValueMap字典,判斷一個或者更加多的Profile屬性值是否被當(dāng)前上下文環(huán)境激活。
現(xiàn)實開發(fā)中可能會有開發(fā)環(huán)境、測試環(huán)境、線上環(huán)境甚至更加多的環(huán)境,他們使用的數(shù)據(jù)源或者一些配置等等都是有差異的,因此它的使用場景也就出來了。
模擬數(shù)據(jù)源配置幾個Bean:

    @Bean("test")
    @Profile("test")
    public ExampleBean exampleBeanOfTest(){
        return new ExampleBean();
    }

    @Bean("dev")
    @Profile("dev")
    public ExampleBean exampleBeanOfDev(){
        return new ExampleBean();
    }

    @Bean("prod")
    @Profile("prod")
    public ExampleBean exampleBeanOfProd(){
        return new ExampleBean();
    }

測試:

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ConfigurableEnvironment environment = ctx.getEnvironment();
        environment.setActiveProfiles("test","dev");//使用代碼配置環(huán)境變量
        ctx.register(BaseConfig.class);
        ctx.refresh();

運行后發(fā)現(xiàn)測試和開發(fā)環(huán)境的2個bean已經(jīng)注冊到容器中了~
或者像上面說的IDE設(shè)置JVM參數(shù)來達(dá)到目的:VM:-Dspring.profiles.active="test","dev"
或者使用@PropertySource加.properties文件同樣可以切換
在resources文件目錄下新建一個application.properties屬性文件,指明環(huán)境變量:spring.profiles.active=prod
后再配置類頭上添加注解@PropertySource("classpath:/application.properties")也可達(dá)到相同的結(jié)果。

import 注解給容器中快速導(dǎo)入一個組件

總結(jié)上面容器注冊bean的方法:1、@Bean注解 2、ComponentScan包掃描+組件標(biāo)注注解 3、import注解
源碼文檔是這樣說的,import能夠?qū)胍粋€或更多的bean,也可以通過實現(xiàn)ImportSelector和ImportBeanDefinitionRegistrar接口來進(jìn)行bean注冊,如果是xml或者其他非bean定義的資源需要被import,可以使用@ImportResource。
這就說明使用import注冊bean組件有3種方式。

直接快速導(dǎo)入

@Configuration
@Import(Computer.class)
//下面是配置類

測試后發(fā)現(xiàn)bean注冊在容器了,bean id為全類名(cn.xxx.xxx.Computer)

實現(xiàn)ImportSelector 接口

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return null;
    }
}

在配置類中:

@Configuration
@Import(MyImportSelector.class)
//下面是配置類

測試跑起來,理論上應(yīng)該是沒有任何bean在容器中注冊的,因為重寫的方法返回null,事實卻報錯了。
::: danger 報錯信息
Failed to process import candidates for configuration class [cn.edu.scau.config.BaseConfig]; nested exception is java.lang.NullPointerException
:::
大致的意思就是空指針異常導(dǎo)致import異常。
源碼跟一下,查看一下方法調(diào)用棧后發(fā)現(xiàn)異常是由一個叫ConfigurationClassParse類捕獲并且拋出來的,查看try代碼塊,有這樣一段代碼:

for (SourceClass candidate : importCandidates) {
                    if (candidate.isAssignable(ImportSelector.class)) {
                        //省略部分源代碼
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                            Collection importSourceClasses = asSourceClasses(importClassNames);
                    }
                    else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                        //省略此邏輯代碼}
                    else {
                        // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                        // process it as an @Configuration class
                        this.importStack.registerImport(
                                currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                        processConfigurationClass(candidate.asConfigClass(configClass));
                    }
                }

結(jié)合這段代碼不難理解,獲取import注解里面類的信息進(jìn)行循環(huán)遍歷,若是實現(xiàn)ImportSelector接口的是一種情況,實現(xiàn)ImportBeanDefinitionRegistrar的也是另一種情況,剩下的就是把他當(dāng)作常規(guī)import進(jìn)行處理。我們這里是實現(xiàn)ImportSelector接口屬于第一種情況,調(diào)用我們重寫selectImports的方法,我們返回給他null,得到一個名為importClassNames的數(shù)組,數(shù)組作為asSourceClasses參數(shù),importClassNames.length,為null的對象使用length當(dāng)然會返回空指針異常,修改一下上面的代碼

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[0];
    }
}

selectImports方法參數(shù):
@ Param AnnotationMetadata :標(biāo)注@Import類(這里為配置類)的類注解信息。
@ Return:返回需要在容器中注冊的bean。bean的id為全類名。如:

return new String[]{"cn.xxx.xxx.bean.Computer"};

實現(xiàn)importBeanDefinitionRegister接口

importBeanDefinitionRegister接口方法參數(shù):
@ Param AnnotationMetadata:同上(注解import這個類的信息)
@ Param BeanDefinitionRegistry:BeanDefinition注冊類,可以使用registerBeanDefinition方法手動注冊進(jìn)來

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean b = registry.containsBeanDefinition("cn.xxx.xxx.bean.Computer");
        if(!b){//沒有Computer這bean就注冊進(jìn)來
            BeanDefinition beanDefinition = new RootBeanDefinition(Computer.class);
            registry.registerBeanDefinition("computer666",beanDefinition);
        }else{//存在的話就移除注冊,容器中也會跟著移除
            registry.removeBeanDefinition("cn.xxx.xxx.bean.Computer");
        }
    }
}
@Configuration
@Import({Computer.class,MyImportBeanDefinitionRegistrar.class})
//配置類

運行后Computer這Bean不在容器中,先import了進(jìn)去后,在MyImportBeanDefinitionRegistrar中又被注冊器給移除了。

FactoryBean注解注冊Bean

這是Spring的工廠bean,實現(xiàn)Factory接口,重寫里面的方法

public class ComputerFactoryBean implements FactoryBean{
    @Override
    public Computer getObject() throws Exception {
        return new Computer();
    }

    @Override
    public Class getObjectType() {
        return Computer.class;
    }
    /*
    * false:代表多實例    true:代表單實例
    */
    @Override
    public boolean isSingleton() {
        return false;
    }
}

`測試:

Object myFactoryBean01 = ctx.getBean("myFactoryBean");
        Object myFactoryBean02 = ctx.getBean("myFactoryBean");
        System.out.println(myFactoryBean01 == myFactoryBean02);
        System.out.println(myFactoryBean01.getClass()+"   "+myFactoryBean02.getClass());

測試后發(fā)現(xiàn),容器中注冊的是ComputerFactoryBean這個代理工廠bean,然而根據(jù)代理工廠的Bean id去容器中取bean對象時又是Computer被代理的bean。那么如何獲取容器中工廠Bean(ComputerFactoryBean)呢。源碼跟一下:
從getBean源碼入手更進(jìn)去在AbstractBeanFactory這個類中發(fā)現(xiàn):

if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }

其中name為getBean(id)我們傳進(jìn)去的,BeanInstance這個對象由AbstractBeanFactory這個類的doGetBean方法里面調(diào)用getSingleton(beanName)這個函數(shù)進(jìn)行獲取,其中beanName由name處理過后的參數(shù),判斷name是否以FACTORY_BEAN_PREFIX(值為&)開頭,不斷循環(huán)去掉&頭得到beanName,返回BeanInstance對象(這個對象就是代理工廠bean),進(jìn)而可以知道想要獲取容器中代理bean通過加&進(jìn)行處理。

        //獲取代理的bean   value=Computer
        Object myFactoryBean01 = ctx.getBean("myFactoryBean");
       //getBean前面加上大于等于1的&符號代表獲取FactoryBean   value = ComputerFactoryBean
        Object myFactoryBean02 = ctx.getBean("&&myFactoryBean");

實際中可能會使用工廠Bean來代理某一個Bean,對該對象的所有方法做一個攔截,進(jìn)行定制化的處理。個人認(rèn)為倒不如使用基于注解的aspectJ做AOP更加來得方便。

歡迎大家關(guān)注一波我的公眾號,嚶嚶嚶(你們的支持是我寫下去的最大動力嗚嗚嗚嗚)

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/74479.html

相關(guān)文章

  • Spring注解專題系類(二)

    摘要:的在單例被破壞時由進(jìn)行方法調(diào)用。定義并實現(xiàn)這兩個接口容器創(chuàng)建完成注解是的縮寫,意思是規(guī)范提案。在創(chuàng)建完成并且屬性賦值完成來執(zhí)行初始化方法在容器銷毀之前回調(diào)通知支持自動裝配,類似。 Spring注解應(yīng)用篇--IOC容器Bean生命周期 這是Spring注解專題系類文章,本系類文章適合Spring入門者或者原理入門者,小編會在本系類文章下進(jìn)行企業(yè)級應(yīng)用實戰(zhàn)講解以及spring源碼跟進(jìn)。本文...

    Alex 評論0 收藏0
  • Java后端

    摘要:,面向切面編程,中最主要的是用于事務(wù)方面的使用。目標(biāo)達(dá)成后還會有去構(gòu)建微服務(wù),希望大家多多支持。原文地址手把手教程優(yōu)雅的應(yīng)用四手把手實現(xiàn)后端搭建第四期 SpringMVC 干貨系列:從零搭建 SpringMVC+mybatis(四):Spring 兩大核心之 AOP 學(xué)習(xí) | 掘金技術(shù)征文 原本地址:SpringMVC 干貨系列:從零搭建 SpringMVC+mybatis(四):Sp...

    joyvw 評論0 收藏0
  • Spring MVC之基于java config無xml配置的web應(yīng)用構(gòu)建

    摘要:更多相關(guān)博文參考前一篇博文講了的方式創(chuàng)建應(yīng)用,用過的童鞋都知道,早就沒有什么事情了,其實的版本,就已經(jīng)支持,不用再寫本篇將介紹下,如何利用取代配置本篇博文,建議和上一篇對比看,貼出上一篇地址之基于配置的應(yīng)用構(gòu)建構(gòu)建項目依賴對于依賴 更多spring相關(guān)博文參考: http://spring.hhui.top 前一篇博文講了SpringMVC+web.xml的方式創(chuàng)建web應(yīng)用,用過S...

    chunquedong 評論0 收藏0
  • Spring Boot 2.x 系列教程:WebFlux REST API 全局異常處理 Error

    摘要:挺多人咨詢的,異常處理用切面注解去實現(xiàn)去全局異常處理。全局異常處理類,代碼如下代碼解析如下抽象類是用來處理全局錯誤時進(jìn)行擴(kuò)展和實現(xiàn)注解標(biāo)記的切面排序,值越小擁有越高的優(yōu)先級,這里設(shè)置優(yōu)先級偏高。 本文內(nèi)容 為什么要全局異常處理? WebFlux REST 全局異常處理實戰(zhàn) 小結(jié) 摘錄:只有不斷培養(yǎng)好習(xí)慣,同時不斷打破壞習(xí)慣,我們的行為舉止才能夠自始至終都是正確的。 一、為什么要全局...

    BicycleWarrior 評論0 收藏0
  • Spring Boot 2 快速教程:WebFlux 快速入門(二)

    摘要:響應(yīng)式編程是基于異步和事件驅(qū)動的非阻塞程序,只是垂直通過在內(nèi)啟動少量線程擴(kuò)展,而不是水平通過集群擴(kuò)展。三特性常用的生產(chǎn)的特性如下響應(yīng)式編程模型適用性內(nèi)嵌容器組件還有對日志消息測試及擴(kuò)展等支持。 摘要: 原創(chuàng)出處 https://www.bysocket.com 「公眾號:泥瓦匠BYSocket 」歡迎關(guān)注和轉(zhuǎn)載,保留摘要,謝謝! 02:WebFlux 快速入門實踐 文章工程: JDK...

    gaara 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<