SpringBoot2.0深度實(shí)踐學(xué)習(xí)筆記(一)之Spring模式注解

springboot的自動(dòng)裝配源于SpringFramework的手動(dòng)裝備,SpringFramework手動(dòng)裝配來看起。

手動(dòng)裝配是按照SpringFramework的版本進(jìn)行管理的,前提差不多都是基于基于注解驅(qū)動(dòng)。

【什么是Spring模式注解】
一種用于聲明在應(yīng)用中扮演“組件”角色的注解
這里的應(yīng)用:在Spring或者SpringBoot應(yīng)用
組件:例如:@Component spring2.5,@Service:服務(wù)類注解 spring2.5,@Configuration 配置注解spring3

github上定義:A stereotype annotation is an annotation that is used to declare the role that a component plays within the application.
github關(guān)于模式注解(Stereotype Annotations)的解釋中最為重要的一點(diǎn)就是:
凡是被 @Component 元標(biāo)注(meta-annotated)的注解,如 @Service ,@Repository等,當(dāng)任何組件標(biāo)注它時(shí),也被視作組件掃描的候選對(duì)象,可以理解為組件 是包括@Component及他的所有“派生”。

常用的模式注解
@Repository 數(shù)據(jù)倉儲(chǔ)模式注解 起始版本2.0
@Component 通用組件模式注解 起始版本 2.5
@Service 服務(wù)模式注解 起始版本2.5
@Controller 控制器模式注解 起始版本2.5
@Configuration 配置類模式注解 起始版本 3.0

【裝配的方式有2種】

1)xml方式:<context:component-scan> spring2.5提出的方案

base-package指明的這個(gè)包下所有的組件都會(huì)被掃描到

<meta charset="utf-8">

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

[http://www.springframework.org/schema/beans/spring-beans.xsd](http://www.springframework.org/schema/beans/spring-beans.xsd)

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-

context.xsd">

<!-- 激活注解驅(qū)動(dòng)特性 -->

<context:annotation-config />

<!-- 找尋被 @Component 或者其派生 Annotation 標(biāo)記的類(Class),將它們注冊(cè)為 Spring Bean  -->

<context:component-scan base-package="com.imooc.dive.in.spring.boot" />

</beans>

2)注解方式:@ComponentScan ,是spring3.1的方案

springboot1.0是基于spring4進(jìn)行開發(fā)。
@ComponentScan(basePackages = "com.imooc.dive.in.spring.boot")
public class SpringConfiguration {
...
}

【Spring Framework手動(dòng)裝配自定義模式注解】
自定義模式注解,有兩個(gè)性質(zhì)@Component “派生性”和@Component “層次性”,我們從一個(gè)小栗子來看看這2個(gè)性質(zhì)的體現(xiàn)

【@Component “派生性”】
注意這里的派生不是真正的派生就是一種理解

【栗子】
新建一個(gè)工程,工程下新建一個(gè)包annotation ,這個(gè)包下新建一個(gè)注解類FirstLevelRepository,作為一級(jí)倉儲(chǔ)

/**
 * 一級(jí) {@link Repository @Repository}
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repository // 數(shù)據(jù)倉儲(chǔ)模式注解
public @interface FirstLevelRepository {

    String value() default "";

}

備注:
@Repository // 數(shù)據(jù)倉儲(chǔ)模式注解
通過源碼可以看到@Repository元標(biāo)注的是@Component,
并且,他們的簽名都保持這一致,屬性方法value()
這就是所謂的“派生性”

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";  //簽名 一致性 :屬性方法value
}


@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
    String value() default "";
}

接下來,我們要將這個(gè)注解作用到一個(gè)類上面
新建一個(gè)包repository,下面新建一個(gè)類MyFirstLevelRepository,類上面添加我們剛才自定義的注解,通過value來添加一個(gè)bean的名稱,注意名字的第一個(gè)字母要小寫,在進(jìn)行組件掃描后MyFirstLevelRepository這個(gè)類就成為一個(gè)bean。

/**
 * 我的{@link FirstLevelRepository}
 */
@FirstLevelRepository(value = "myFirstLevelRepository")   //Bean的名字
public class MyFirstLevelRepository {
}

我們新建一個(gè)bootstrap包,下面建一個(gè)引導(dǎo)類,就是啟動(dòng)類RepositoryBootstrap,這里我們不使用注解@SpringBootApplication來標(biāo)注引導(dǎo)類,我們采用SpringApplicationBuilder()spring2.0寫法。
可以指定類型web,我們定義為非web類型 ,一個(gè)普通類型,注解驅(qū)動(dòng)

/**
 * 倉儲(chǔ)引導(dǎo)類
 */
@ComponentScan(basePackages = "com.cbt.diveinspringboot.repository")
public class RepositoryBootstrap {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(RepositoryBootstrap.class)
                .web(WebApplicationType.NONE)
                .run(args);

        // myFirstLevelRepository Bean是否存在
        MyFirstLevelRepository myFirstLevelRepository = context.getBean("myFirstLevelRepository",MyFirstLevelRepository.class);

        System.out.println("myFirstLevelRepository Bean:" + myFirstLevelRepository);

        context.close();
    }
}

說明
1、run()返回的對(duì)象 ConfigurableApplicationContext
2、關(guān)閉上下文context
3、掃描MyFirstLevelRepository 這個(gè)類的方式:
1)可以包MyFirstLevelRepository這個(gè)bean丟進(jìn)去
2)也可以把RepositoryBootstrap 這個(gè)bean丟進(jìn)去
4、這里先采用注解@ComponentScan 的裝配方式,這個(gè)@FirstLevelRepository組件可以用來識(shí)別我們的MyFirstLevelRepository類。
通過@ComponentScan 掃描包下所有的類,
類被@FirstLevelRepository標(biāo)記的就會(huì)被認(rèn)為是一個(gè)bean,我們可以通過Bean的名稱進(jìn)行獲取。
通過上下文對(duì)象去獲取到bean,第一個(gè)參數(shù)是bean的名稱,就是通過類上的注解value獲取的,第二個(gè)參數(shù)bean的類型,這種方式不用進(jìn)行類型強(qiáng)轉(zhuǎn)的

運(yùn)行引導(dǎo)類:結(jié)果顯示進(jìn)行組件掃描后MyFirstLevelRepository這個(gè)類就成為一個(gè)bean了。


1.png

如果你采用@Component注解來替換我們自定義的注解@ FirstLevelRepository結(jié)果是一樣的 ,你可以自己運(yùn)行看看 ----這就是所謂的“派生性”
可以一直注解上去

@Component(value = "myFirstLevelRepository")
public class MyFirstLevelRepository {
}

【@Component “層次性”】就是自定義的注解還可以用來標(biāo)注在其他自定義的注解上面
在annotation包下新建注解SecondLevelRepository
簽名要保持一致

/**
 * 二級(jí){@link Repository }
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@FirstLevelRepository  //標(biāo)注自定義注解
public @interface SecondLevelRepository {
    String value() default "";
}

將這個(gè)@SecondLevelRepository注解添加到MyFirstLevelRepository類

/**
 * 我的{@link SecondLevelRepository}
 */
@SecondLevelRepository(value = "myFirstLevelRepository")
public class MyFirstLevelRepository {
}

層次關(guān)系:

  1. @Component
    2.@Repository
    3.@FirstLevelRepository
    4.@SecondLevelRepository

運(yùn)行引導(dǎo)類:結(jié)果和上面是一樣的。

我們可以再看一個(gè)栗子:
注解:@SpringBootApplication

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

看一下里面的:@SpringBootConfiguration這個(gè)注解,這個(gè)注解標(biāo)注@Configuration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}

@Configuration注解又元標(biāo)注了@Component

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

說明@SpringBootApplication也是屬于模式注解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容