Spring注解詳解大全


主件注冊(cè)

- @Configuration

@Configuration即用來(lái)代替Spring配置文件的车柠,它就是一個(gè)@Component組件,接收一個(gè)value值也就是bean的名字骡尽,value可以不填遣妥。Spring會(huì)自動(dòng)掃描包下面的@Configuration注解的配置文件類(lèi)來(lái)裝配。


@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Component

public @interface Configuration {

    @AliasFor(

        annotation = Component.class

    )

    String value() default "";

}

- @Bean

@Bean相當(dāng)于Spring配置文件中的<bean />標(biāo)簽可以在Spring容器中注入一個(gè)bean:

- 1. @Bean注解在返回實(shí)例的方法上攀细,如果未通過(guò)@Bean指定bean的名稱(chēng)箫踩,則默認(rèn)與方法名相同

- 2. @Bean注解默認(rèn)作用域?yàn)閱卫齭ingleton作用域,可通過(guò)@Scope(“prototype”)設(shè)置為多例

@Configuration

public class TestConfiguration {

    @Bean

    public TestBean testBean() {

        return new TestBean();

    }

}

上面的代碼就會(huì)向Spring容器中實(shí)例一個(gè)TestBean對(duì)象谭贪,并且該Bean對(duì)象的名稱(chēng)為testBean

- @ComponentScan

@ComponentScan 的作用就是根據(jù)定義的掃描路徑境钟,把符合掃描規(guī)則的類(lèi)裝配到spring容器中。注意:被掃描的包下面的類(lèi)只能有以下注解俭识,才會(huì)被創(chuàng)建加入到IOC中去:

- 1. @Component:沒(méi)有明確的角色

- 2. @Service:業(yè)務(wù)層角色

- 3. @Repository:持久層角色

- 4. @Controller:控制層角色

注解定義如下:


@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.TYPE})

@Documented

@Repeatable(ComponentScans.class)

public @interface ComponentScan {

    @AliasFor("basePackages")

    String[] value() default {};

    @AliasFor("value")

    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "";

    boolean useDefaultFilters() default true;

    ComponentScan.Filter[] includeFilters() default {};

    ComponentScan.Filter[] excludeFilters() default {};

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)

    @Target({})

    public @interface Filter {

        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")

        Class<?>[] value() default {};

        @AliasFor("value")

        Class<?>[] classes() default {};

        String[] pattern() default {};

    }

}

- 1.basePackages與value:  用于指定包的路徑慨削,進(jìn)行掃描

- 2.basePackageClasses: 用于指定某個(gè)類(lèi)的包的路徑進(jìn)行掃描

- 3.nameGenerator: bean的名稱(chēng)的生成器

- 4.useDefaultFilters: 是否開(kāi)啟對(duì)@Component,@Repository套媚,@Service缚态,@Controller的類(lèi)進(jìn)行檢測(cè),默認(rèn)開(kāi)啟

- 5.includeFilters: 包含的過(guò)濾條件:

        FilterType.ANNOTATION:按照注解過(guò)濾

        FilterType.ASSIGNABLE_TYPE:按照給定的類(lèi)型

        FilterType.ASPECTJ:使用ASPECTJ表達(dá)式

        FilterType.REGEX:正則

        FilterType.CUSTOM:自定義規(guī)則

- 6.excludeFilters: 排除的過(guò)濾條件:

        FilterType.ANNOTATION:按照注解過(guò)濾

        FilterType.ASSIGNABLE_TYPE:按照給定的類(lèi)型

        FilterType.ASPECTJ:使用ASPECTJ表達(dá)式

        FilterType.REGEX:正則

        FilterType.CUSTOM:自定義規(guī)則

- 7.lazyInit:是否進(jìn)行懶加載,默認(rèn)為false

例子:

工程目錄結(jié)構(gòu)如圖:

工程目錄結(jié)構(gòu)

1.掃描service包下的類(lèi):


@Configuration

@ComponentScan(value = "com.xhx.spring.service",useDefaultFilters = true)

public class MyConfig {

}

2.掃描service包下的類(lèi)和HelloController類(lèi)所在包下的所有類(lèi)


@Configuration

@ComponentScan(value = "com.xhx.spring.service",

        useDefaultFilters = true,

        basePackageClasses = HelloController.class

)

public class MyConfig {

}

3.只掃描指定包下的Controller注解標(biāo)記的類(lèi)添加到IOC容器中去


@Configuration

@ComponentScan(value = "com.xhx.spring",

        useDefaultFilters = false,

        includeFilters = {

            @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})

        }

)

public class MyConfig {

}

4.掃描指定包下指定類(lèi)型的類(lèi)到IOC容器中堤瘤。(即使指定類(lèi)型的類(lèi)沒(méi)有加注解也能被掃描到IOC容器中去)


@Configuration

@ComponentScan(value = "com.xhx.spring",

        useDefaultFilters = false,

        includeFilters = {

            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {HelloController.class})

        }

)

public class MyConfig {

}

這里即使HelloController類(lèi)沒(méi)有加@Controller猿规、@Service、@Component宙橱、@Repository注解也能被掃描到IOC容器中去。

5.指定包路徑蘸拔,按照自定義掃描規(guī)則進(jìn)行掃描

自定義掃描規(guī)則:自定義規(guī)則必須實(shí)現(xiàn)TypeFilter接口


package com.xhx.spring.componentscan.config;

import org.springframework.core.type.classreading.MetadataReader;

import org.springframework.core.type.classreading.MetadataReaderFactory;

import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

/**

* 2018/9/18 23:07

**/

public class MyTypeFilter implements TypeFilter {

    @Override

    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {

        //MetadataReader該參數(shù)可以獲取指定路徑下所有類(lèi)的任何信息

        //MetadataReaderFactory是MetadataReader工廠

        String className = metadataReader.getClassMetadata().getClassName();

        if(className.contains("Controller")){

            return true;

        }

        return false;

    }

}

自定義配置類(lèi):


@Configuration

@ComponentScan(value = "com.xhx.spring",

        useDefaultFilters = false,

        includeFilters = {

            @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})

        }

)

public class MyConfig {

}

- @Scope

spring中scope是一個(gè)非常關(guān)鍵的概念师郑,簡(jiǎn)單說(shuō)就是對(duì)象在spring容器(IOC容器)中的生命周期,也可以理解為對(duì)象在spring容器中的創(chuàng)建方式调窍。

scope分類(lèi):

在Spring 2.0之前宝冕,有singleton和prototype兩種;

在Spring 2.0之后邓萨,為支持web應(yīng)用的ApplicationContext地梨,增強(qiáng)另外三種:request,session和global session類(lèi)型缔恳,它們只實(shí)用于web程序宝剖,通常是和XmlWebApplicationContext共同使用。

- @Lazy

該注解是在單實(shí)例bean是使用歉甚,當(dāng)使用@Scope注解的singleton屬性時(shí)万细,bean的實(shí)例會(huì)在IOC容器創(chuàng)建的時(shí)候被加載,但是如果在創(chuàng)建bean的時(shí)候加上@lazy注解纸泄,則bean的實(shí)例會(huì)在第一次使用的時(shí)候被創(chuàng)建赖钞。


    @Lazy

    @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)//singleton

    @Bean(name = "person")

    public Person person(){

        Person person = new Person();

        person.setName("lqf");

        person.setEmail("lqf@163.com");

        return person;

    }

- @Conditional

@Conditional 注解腰素,根據(jù)是否滿(mǎn)足指定的條件來(lái)決定是否裝配 Bean 。Conditional 是由 SpringFramework 提供的一個(gè)注解雪营,位于 org.springframework.context.annotation 包內(nèi)弓千,定義如下:


@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Conditional {

/**

* All {@link Condition}s that must {@linkplain Condition#matches match}

* in order for the component to be registered.

*/

Class<? extends Condition>[] value();

}

Conditional 注解類(lèi)里只有一個(gè) value 屬性,需傳入一個(gè) Condition 類(lèi)型的數(shù)組献起,我們先來(lái)看看這個(gè) Condition 接口長(zhǎng)什么樣:


@FunctionalInterface

public interface Condition {

/**

* Determine if the condition matches.

* @param context the condition context

* @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}

* or {@link org.springframework.core.type.MethodMetadata method} being checked

* @return {@code true} if the condition matches and the component can be registered,

* or {@code false} to veto the annotated component's registration

*/

boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

其中洋访,matches() 方法傳入的參數(shù) ConditionContext 是專(zhuān)門(mén)為 Condition 而設(shè)計(jì)的一個(gè)接口類(lèi),可以從中獲取到Spring容器的以下對(duì)象信息:

- ConditionContext

    - getRegistry():獲取BeanDefinitionRegistry

    - getBeanFactory():獲取ConfigurableListableBeanFactory

    - getEnvironment():獲取Environment

    - getResourceLoader():獲取ResourceLoader對(duì)象

    - getClassLoader():獲取ClassLoader對(duì)象

當(dāng)一個(gè) Bean 被 Conditional 注解修飾時(shí)征唬,Spring容器會(huì)對(duì)數(shù)組中所有 Condition 接口的 matches() 方法進(jìn)行判斷捌显,只有當(dāng)其中所有 Condition 接口的 matches()方法都為 ture 時(shí),才會(huì)創(chuàng)建 Bean 总寒。

- @Import

@Import可以導(dǎo)入一些有規(guī)律的組件扶歪。@Import定義如下:


@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Import {

/**

* {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}

* or regular component classes to import.

*/

Class<?>[] value();

}

  • 1.導(dǎo)入普通類(lèi)型

Student類(lèi):


public class Student {

}

配置類(lèi):


@Configuration

@Import(Student.class)

public class ImportConfig {

}

  • 2.ImportSelector選擇一些需要導(dǎo)入的組件

MySelector 類(lèi):


public class MySelector implements ImportSelector {

    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        return new String[]{"me.sjl.bean.Person"};

    }

}

配置類(lèi):


@Configuration

@Import(MySelector.class)

public class ImportConfig {

}

  • 3.ImportBeanDefinitionRegistrar導(dǎo)入添加BeanDefinition中的組件

MyBeanDefinitionRegistrat :


public class MyBeanDefinitionRegistrat implements ImportBeanDefinitionRegistrar {


    @Override

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        BeanDefinition beanDefinition = new RootBeanDefinition(Person.class);

        registry.registerBeanDefinition("PERSON", beanDefinition);

    }

}

配置類(lèi):


@Configuration

@Import(MyBeanDefinitionRegistrat.class)

public class ImportConfig {

}


生命周期

Bean的生命周期:bean創(chuàng)建 —— 初始胡 —— 銷(xiāo)毀過(guò)程

- @Bean(initMethod="",destroyMethod="")

通過(guò)@Bean注解中的initMethod和destroyMethod屬性指定初始化方法和銷(xiāo)毀方法。

創(chuàng)建一個(gè)Person類(lèi)摄闸,并指定初始化方法和銷(xiāo)毀方法:


public class Person{

    public Person(){

        System.out.println("person controct ...");

    }


    public init(){

        System.out.println("person init ...");

    }


    public destroy(){

        System.out.println("person destroy ...");

    }

}

創(chuàng)建配置類(lèi)善镰,把Person類(lèi)注進(jìn)到IOC容器中,并指定初始化方法和銷(xiāo)毀方法:


@Configuration

public class MyConfiguration{

    @Bean(initMethod="init",destroyMethod="destroy")

    public Person person(){

        return new Person();

    }

}

- InitializingBeanDisposableBean接口

通過(guò)讓Bean實(shí)現(xiàn)InitializingBean接口定義初始化邏輯年枕,實(shí)現(xiàn)DisposableBean接口定義銷(xiāo)毀邏輯

創(chuàng)建一個(gè)Dog類(lèi)炫欺,并實(shí)現(xiàn)InitializingBean接口和DisposableBean來(lái)定義初始化邏輯和銷(xiāo)毀邏輯:


@Component

public class Dog implements InitializingBean,DisposableBean {

    public Dog(){

        System.out.println("Dog controcter");

    }


    //銷(xiāo)毀方法

    @Override

    public void destroy() throws Exception{

        System.out.println("Dog destory ...");

    }


    //初始化方法

    @Override

    public void afterPropertiesSet() throws Exception {

        System.out.println("Dog afterPropertiesSet ...");

    }

}

- @PostConstruct@PreDestroy

通過(guò)使用JSR250:@PostConstruct注解(該注解標(biāo)注在方法上,在bean創(chuàng)建完成后熏兄,并且屬性賦值完成品洛,就來(lái)執(zhí)行該注解標(biāo)注的方法進(jìn)行初始化)。@PreDestroy注解(該注解標(biāo)注在方法上摩桶,當(dāng)容器銷(xiāo)毀前通知該注解標(biāo)記的方法進(jìn)行清理相關(guān)的工作)桥状。

創(chuàng)建一個(gè)Car類(lèi),并通過(guò)@PostConstruct@PreDestroy標(biāo)記的初始化方法和銷(xiāo)毀方法:


@Component

public class Car{

    public Car(){

        System.out.println("Car constructor ...");

    }


    @PostConstruct

    public void init(){

        System.out.println("Car init ...");

    }


    @PreDestroy

    public void destroy(){

        System.out.println("Car destroy ...");

    }

}


屬性賦值


自動(dòng)裝配


統(tǒng)一異常捕獲

- @ControllerAdvice


- @ModelAttribute

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末硝清,一起剝皮案震驚了整個(gè)濱河市辅斟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芦拿,老刑警劉巖士飒,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蔗崎,居然都是意外死亡酵幕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)蚁趁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)裙盾,“玉大人,你說(shuō)我怎么就攤上這事》伲” “怎么了庐完?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)徘熔。 經(jīng)常有香客問(wèn)我门躯,道長(zhǎng),這世上最難降的妖魔是什么酷师? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任讶凉,我火速辦了婚禮,結(jié)果婚禮上山孔,老公的妹妹穿的比我還像新娘懂讯。我一直安慰自己,他們只是感情好台颠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布褐望。 她就那樣靜靜地躺著,像睡著了一般串前。 火紅的嫁衣襯著肌膚如雪瘫里。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,698評(píng)論 1 305
  • 那天荡碾,我揣著相機(jī)與錄音谨读,去河邊找鬼。 笑死坛吁,一個(gè)胖子當(dāng)著我的面吹牛劳殖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拨脉,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼闷尿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了女坑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤统舀,失蹤者是張志新(化名)和其女友劉穎匆骗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體誉简,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碉就,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了闷串。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瓮钥。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碉熄,到底是詐尸還是另有隱情桨武,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布锈津,位于F島的核電站呀酸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏琼梆。R本人自食惡果不足惜性誉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望茎杂。 院中可真熱鬧错览,春花似錦、人聲如沸煌往。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)携冤。三九已至悼粮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曾棕,已是汗流浹背扣猫。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翘地,地道東北人申尤。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像衙耕,于是被迫代替她去往敵國(guó)和親昧穿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

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