2追葡、組件注冊(cè)相關(guān)注解

本節(jié)主要內(nèi)容介紹spring注解的組件注冊(cè),具體包括下面的幾個(gè)注解:

  • @ComponentScan自動(dòng)掃面組件
  • @Scope設(shè)置組件的作用域
  • @Lazy bean組件懶加載
  • @Conditional按照條件注冊(cè)Bean
  • @Import給容器中導(dǎo)入一個(gè)組件

1、@ComponentScan自動(dòng)掃面組件

  • 源碼
@Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
//可以重復(fù)使用
    @Repeatable(ComponentScans.class)
    public @interface ComponentScan {
//使用包名
        @AliasFor("basePackages")
        String[] value() default {};
        @AliasFor("value")
        String[] basePackages() default {};
//使用具體類型名稱
        Class<?>[] basePackageClasses() default {};
        ....其他屬性
//指定掃描的時(shí)候只需要包含哪些組件
        Filter[] includeFilters() default {};
//指定掃描的時(shí)候按照什么規(guī)則排除那些組件
        Filter[] excludeFilters() default {};
        boolean lazyInit() default false;
//過濾規(guī)則類
        @Retention(RetentionPolicy.RUNTIME)
        @Target({})
        @interface Filter {
//FilterType定義按什么過濾類型來進(jìn)行過濾非凌,
/**
FilterType.ANNOTATION:按照注解
FilterType.ASSIGNABLE_TYPE:按照給定的類型;
FilterType.ASPECTJ:使用ASPECTJ表達(dá)式
FilterType.REGEX:使用正則指定
FilterType.CUSTOM:使用自定義規(guī)則
*/
            FilterType type() default FilterType.ANNOTATION;
            @AliasFor("classes")
            Class<?>[] value() default {};
            @AliasFor("value")
            Class<?>[] classes() default {};
            String[] pattern() default {};

        }

    }
  • 使用說明
1荆针、只包含有Controller注解bean
@ComponentScan(value="com.qiu",includeFilters = {
                @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),}
,useDefaultFilters = false)
2敞嗡、排除含有controller注解的bean
@ComponentScan(value="com.qiu",excludeFilters = {
    @Filter(type=FilterType.ANNOTATION,classes={Controller.class})
})  

2、@Scope設(shè)置組件的作用域

  • 源碼
//作用與類或者方法上
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Scope {
        @AliasFor("scopeName")
        String value() default "";
        @AliasFor("value")
        String scopeName() default "";
        ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
    }
  • 使用
*默認(rèn)是單實(shí)例的航背,ConfigurableBeanFactory接口含有者兩個(gè)屬性
*單實(shí)例和原型實(shí)例說明:prototype:多實(shí)例的:ioc容器啟動(dòng)并不會(huì)去調(diào)用方法創(chuàng)建對(duì)象放在容器中喉悴。 
每次獲取的時(shí)候才會(huì)調(diào)用方法創(chuàng)建對(duì)象;singleton:單實(shí)例的(默認(rèn)值):ioc容器啟動(dòng)會(huì)調(diào)用方法創(chuàng)建
對(duì)象放到ioc容器中沃粗。 以后每次獲取就是直接從容器(map.get())中拿
1粥惧、原型案例
@Scope("prototype")
    @Bean()
    public User user() {
        System.out.println("給容器中添加user....");
        return new User();
    }
2、測(cè)試
ConfigurableApplicationContext context2=new 
AnnotationConfigApplicationContext(ScopeConfig.class);
        //測(cè)試scope:獲取容器中的bean,singleton單例時(shí)候相等最盅,prototype時(shí)候不相等
        User user2=(User) context2.getBean("user");
        User user1=(User) context2.getBean("user");
        System.out.println(user1==user2);

3突雪、@Lazy bean組件懶加載

  • @Lazy注解用于標(biāo)識(shí)bean是否需要延遲加載,默認(rèn)是true涡贱。當(dāng)沒加注解之前主要容器啟動(dòng)就會(huì)實(shí)例化bean,加上@Lazy注解則必須在第一次調(diào)用的時(shí)候才會(huì)加載如下:
1咏删、沒加注解之前主要容器啟動(dòng)就會(huì)實(shí)例化bean
        ConfigurableApplicationContext context2=new 
AnnotationConfigApplicationContext(ScopeConfig.class);
2、加入@Lazy后必須第一次調(diào)用的時(shí)候才會(huì)加載
User user3=(User) context2.getBean("user1");

4问词、@Conditional按照條件注冊(cè)Bean

  • 源碼
//作用于方法和類
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
//參數(shù)是:繼承于Condition的類數(shù)組
    Class<? extends Condition>[] value();
}
//condition接口督函,自定義的condition類需要實(shí)現(xiàn)該接口
public interface Condition {
/**
     * ConditionContext:判斷條件能使用的上下文(環(huán)境)
     * AnnotatedTypeMetadata:注釋信息
     */
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
  • 案例說明
    需求:按照當(dāng)前操作系統(tǒng)來注入相應(yīng)的Bean,如果系統(tǒng)是windows激挪,給容器中注冊(cè)("bill")辰狡,如果是linux系統(tǒng),給容器中注冊(cè)("linus")
1垄分、判斷是否是linux系統(tǒng)
public class LinuxCondition implements Condition{
    /**
     * ConditionContext:判斷條件能使用的上下文(環(huán)境)
     * AnnotatedTypeMetadata:注釋信息
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) 
{
        //1.能獲取到ioc使用的Beanfactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //2宛篇、獲取到類加載器
        ClassLoader classLoader = context.getClassLoader();
        //3.獲取到當(dāng)前環(huán)境信息
        Environment environment = context.getEnvironment();
        //4.獲取到bean定義的注冊(cè)類信息
        BeanDefinitionRegistry registry = context.getRegistry();
        //=============這里主要是為了獲取當(dāng)前系統(tǒng)的環(huán)境變臉
        String property=environment.getProperty("os.name");
        if (property.contains("linux")) {
            return true;//放行
        }
        return false;
    }

}

2、判斷是否是windows系統(tǒng)
public class WindowsCondition implements Condition{
    /**
     * ConditionContext:判斷條件能使用的上下文(環(huán)境)
     * AnnotatedTypeMetadata:注釋信息
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata)
 {
        Environment environment = context.getEnvironment();
        String property=environment.getProperty("os.name");
        if (property.contains("Windows")) {
            return true;//放行
        }
        return false;
    }
}
3薄湿、@Conditional:按照一定的邏輯進(jìn)行判斷叫倍,滿足條件給容器注入bean
public class ConditionalConfig {
//注入windows
    @Conditional(value= {WindowsCondition.class})
    @Bean
    public User user1() {
        User user=new User();
        user.setUserName("bill");
        return user;
    }
//注入linux
    @Conditional(value= {LinuxCondition.class})
    @Bean
    public User user2() {
        User user=new User();
        user.setUserName("linus");
        return user;
    }
4、idea中更換操作系統(tǒng)方法:-Dos.name=linux

介紹完了條件注解在spring中的使用豺瘤,在Springboot中條件注解的分類:

Class conditions:@ConditionalOnClass和@ConditionalOnMissingClass吆倦,表示類是否在類路徑下的條件注解
Bean conditions:@ConditionalOnBean和@ConditionalOnMissingBean,表示Bean是否被定義的條件注解
Property conditions:@ConditionalOnProperty坐求,使用prefix和name屬性用來表示是否有值蚕泽,默認(rèn)的話,只要該屬性存在值桥嗤,且不為false赛糟,即可匹配
Resource conditions:@ConditionalOnResource表示是否存在指定的resouce的條件注解
Web application conditions:@ConditionalOnWebApplication和@ConditionalOnNotWebApplication派任,當(dāng)項(xiàng)目是web項(xiàng)目,或者不是web項(xiàng)目的條件注解
SpEL expression conditions:@ConditionalOnExpression璧南,根據(jù)SPEL表達(dá)式執(zhí)行結(jié)果作為條件

5、@Import給容器中導(dǎo)入一個(gè)組件

  • 源碼
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
//只有一個(gè)屬性师逸,類型數(shù)組
    Class<?>[] value();
}
  • 給容器中注冊(cè)組件方式:

1司倚、包掃描+組件標(biāo)注注解(@Controller/@Service/@Repository/@Component)[自己寫的類]
2、@Bean[導(dǎo)入的第三方包里面的組件或者自己寫的]
3篓像、@Import[快速給容器中導(dǎo)入一個(gè)組件动知,常用于框架中]
(1)、@Import(要導(dǎo)入到容器中的組件)员辩;容器中就會(huì)自動(dòng)注冊(cè)這個(gè)組件盒粮,id默認(rèn)是全類名
(2)、ImportSelector:返回需要導(dǎo)入的組件的全類名數(shù)組奠滑;
(3)丹皱、ImportBeanDefinitionRegistrar:手動(dòng)注冊(cè)bean到容器中
4、使用Spring提供的 FactoryBean(工廠Bean);
(1)默認(rèn)獲取到的是工廠bean調(diào)用getObject創(chuàng)建的對(duì)象

  • @Import注入組件案例說明:
1宋税、@Import(要導(dǎo)入到容器中的組件)
@Import(value= {Person.class})
2摊崭、ImportSelector:返回需要導(dǎo)入的組件的全類名數(shù)組;
//先自定義邏輯返回需要導(dǎo)入的組件
public class MyImportSelector implements ImportSelector {
    //返回值杰赛,就是到導(dǎo)入到容器中的組件全類名
    //AnnotationMetadata:當(dāng)前標(biāo)注@Import注解的類的所有注解信息
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //importingClassMetadata
        //方法不要返回null值
        return new String[]{"com.huya.qiu.model.BlackPerson",
"com.huya.qiu.model.WhitePerson"};
    }
}
//然后注入
@Import(value= {MyImportSelector.class})
3呢簸、ImportBeanDefinitionRegistrar:手動(dòng)注冊(cè)bean到容器中
//先實(shí)現(xiàn)ImportBeanDefinitionRegistrar接口
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * AnnotationMetadata:當(dāng)前類的注解信息
     * BeanDefinitionRegistry:BeanDefinition注冊(cè)類;
     *      把所有需要添加到容器中的bean乏屯;調(diào)用
     *      BeanDefinitionRegistry.registerBeanDefinition手工注冊(cè)進(jìn)來
     */
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //當(dāng)同時(shí)擁有下面兩個(gè)注冊(cè)bean時(shí)候也注冊(cè)yellowPerson
        boolean definition = registry.containsBeanDefinition("com.huya.qiu.model.BlackPerson");
        boolean definition2 = registry.containsBeanDefinition("com.huya.qiu.model.WhitePerson");
        if(definition && definition2){
            //指定Bean定義信息根时;(Bean的類型,Bean辰晕。蛤迎。。)
            RootBeanDefinition beanDefinition = new RootBeanDefinition(YellowPerson.class);
            //注冊(cè)一個(gè)Bean伞芹,指定bean名
            registry.registerBeanDefinition("yellowPerson", beanDefinition);
        }
    }
}
//然后注入
@Import(value= {MyImportBeanDefinitionRegistrar.class})

  • 使用Spring提供的 FactoryBean注入組價(jià)案例說明
1忘苛、創(chuàng)建一個(gè)Spring定義的FactoryBean
public class PersonFactoryBean implements FactoryBean<Person> {

    //返回一個(gè)Person對(duì)象,這個(gè)對(duì)象會(huì)添加到容器中
    public Person getObject() throws Exception {
        System.out.println("PersonFactoryBean...getObject...");
        return new Person();
    }

    public Class<?> getObjectType() {
        return Person.class;
    }

    //是單例唱较?
    public boolean isSingleton() {
        return false;
    }

}
2扎唾、注入相應(yīng)的bean
@Bean
    public PersonFactoryBean personFactoryBean(){
        return new PersonFactoryBean();
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市南缓,隨后出現(xiàn)的幾起案子胸遇,更是在濱河造成了極大的恐慌,老刑警劉巖汉形,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纸镊,死亡現(xiàn)場離奇詭異倍阐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)逗威,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門峰搪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凯旭,你說我怎么就攤上這事概耻。” “怎么了罐呼?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵鞠柄,是天一觀的道長。 經(jīng)常有香客問我嫉柴,道長厌杜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任计螺,我火速辦了婚禮夯尽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘危尿。我一直安慰自己呐萌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布谊娇。 她就那樣靜靜地躺著肺孤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪济欢。 梳的紋絲不亂的頭發(fā)上赠堵,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音法褥,去河邊找鬼茫叭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛半等,可吹牛的內(nèi)容都是我干的揍愁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼杀饵,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼莽囤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起切距,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤朽缎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體话肖,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡北秽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了最筒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贺氓。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖床蜘,靈堂內(nèi)的尸體忽然破棺而出掠归,到底是詐尸還是另有隱情,我是刑警寧澤悄泥,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站肤粱,受9級(jí)特大地震影響弹囚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜领曼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一鸥鹉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧庶骄,春花似錦毁渗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至羔飞,卻和暖如春肺樟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逻淌。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工么伯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卡儒。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓田柔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親骨望。 傳聞我的和親對(duì)象是個(gè)殘疾皇子硬爆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1.1 Spring IoC容器和bean簡介 本章介紹了Spring Framework實(shí)現(xiàn)的控制反轉(zhuǎn)(IoC)...
    起名真是難閱讀 2,583評(píng)論 0 8
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器,...
    simoscode閱讀 6,713評(píng)論 2 22
  • 內(nèi)容過長锦募,core部分分開發(fā)布摆屯,core章節(jié)第二部分點(diǎn)擊:Spring Framework 官方文檔中文版—Cor...
    kopshome閱讀 33,675評(píng)論 7 24
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,810評(píng)論 6 342
  • 標(biāo)題:如何用好上班的八個(gè)小時(shí) 記得上小學(xué)時(shí),周六上午是要上課,周六下午才放假虐骑,那時(shí)周末只有一天半准验。從保障勞動(dòng)者充分...
    開啟2017閱讀 146評(píng)論 3 2