SpringBoot2.0深度实践学习笔记(一)之Spring模式注解

springboot的自动装配源于SpringFramework的手动装备,SpringFramework手动装配来看起。

手动装配是按照SpringFramework的版本进行管理的,前提差不多都是基于基于注解驱动。

【什么是Spring模式注解】
一种用于声明在应用中扮演“组件”角色的注解
这里的应用:在Spring或者SpringBoot应用
组件:例如:@Component spring2.5,@Service:服务类注解 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关于模式注解(Stereotype Annotations)的解释中最为重要的一点就是:
凡是被 @Component 元标注(meta-annotated)的注解,如 @Service ,@Repository等,当任何组件标注它时,也被视作组件扫描的候选对象,可以理解为组件 是包括@Component及他的所有“派生”。

常用的模式注解
@Repository 数据仓储模式注解 起始版本2.0
@Component 通用组件模式注解 起始版本 2.5
@Service 服务模式注解 起始版本2.5
@Controller 控制器模式注解 起始版本2.5
@Configuration 配置类模式注解 起始版本 3.0

【装配的方式有2种】

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

base-package指明的这个包下所有的组件都会被扫描到

<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">

<!-- 激活注解驱动特性 -->

<context:annotation-config />

<!-- 找寻被 @Component 或者其派生 Annotation 标记的类(Class),将它们注册为 Spring Bean  -->

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

</beans>

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

springboot1.0是基于spring4进行开发。
@ComponentScan(basePackages = "com.imooc.dive.in.spring.boot")
public class SpringConfiguration {
...
}

【Spring Framework手动装配自定义模式注解】
自定义模式注解,有两个性质@Component “派生性”和@Component “层次性”,我们从一个小栗子来看看这2个性质的体现

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

【栗子】
新建一个工程,工程下新建一个包annotation ,这个包下新建一个注解类FirstLevelRepository,作为一级仓储

/**
 * 一级 {@link Repository @Repository}
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repository // 数据仓储模式注解
public @interface FirstLevelRepository {

    String value() default "";

}

备注:
@Repository // 数据仓储模式注解
通过源码可以看到@Repository元标注的是@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 "";
}

接下来,我们要将这个注解作用到一个类上面
新建一个包repository,下面新建一个类MyFirstLevelRepository,类上面添加我们刚才自定义的注解,通过value来添加一个bean的名称,注意名字的第一个字母要小写,在进行组件扫描后MyFirstLevelRepository这个类就成为一个bean。

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

我们新建一个bootstrap包,下面建一个引导类,就是启动类RepositoryBootstrap,这里我们不使用注解@SpringBootApplication来标注引导类,我们采用SpringApplicationBuilder()spring2.0写法。
可以指定类型web,我们定义为非web类型 ,一个普通类型,注解驱动

/**
 * 仓储引导类
 */
@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()返回的对象 ConfigurableApplicationContext
2、关闭上下文context
3、扫描MyFirstLevelRepository 这个类的方式:
1)可以包MyFirstLevelRepository这个bean丢进去
2)也可以把RepositoryBootstrap 这个bean丢进去
4、这里先采用注解@ComponentScan 的装配方式,这个@FirstLevelRepository组件可以用来识别我们的MyFirstLevelRepository类。
通过@ComponentScan 扫描包下所有的类,
类被@FirstLevelRepository标记的就会被认为是一个bean,我们可以通过Bean的名称进行获取。
通过上下文对象去获取到bean,第一个参数是bean的名称,就是通过类上的注解value获取的,第二个参数bean的类型,这种方式不用进行类型强转的

运行引导类:结果显示进行组件扫描后MyFirstLevelRepository这个类就成为一个bean了。


1.png

如果你采用@Component注解来替换我们自定义的注解@ FirstLevelRepository结果是一样的 ,你可以自己运行看看 ----这就是所谓的“派生性”
可以一直注解上去

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

【@Component “层次性”】就是自定义的注解还可以用来标注在其他自定义的注解上面
在annotation包下新建注解SecondLevelRepository
签名要保持一致

/**
 * 二级{@link Repository }
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@FirstLevelRepository  //标注自定义注解
public @interface SecondLevelRepository {
    String value() default "";
}

将这个@SecondLevelRepository注解添加到MyFirstLevelRepository类

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

层次关系:

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

运行引导类:结果和上面是一样的。

我们可以再看一个栗子:
注解:@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这个注解,这个注解标注@Configuration

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

}

@Configuration注解又元标注了@Component

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

说明@SpringBootApplication也是属于模式注解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容