走向自动装配|第一章-Spring Framework 手动装配

走向自动装配|第一章-Spring Framework 手动装配

文章说明

Spring Framework 到 Spring Boot 怎么一步一步走向自动装配

项目环境

1.Spring 模式注解装配

定义:一种用于声明在应用中扮演 组件 角色的注解

举例:@Component、@Service、@Configuration 等

装配:<context:component-scan …> 或者 @ComponentScan

2.Stereotype Annotations 模式注解

Spring 官网文档

A stereotype annotation is an annotation that is used to declare the role that a component plays within the application. For example, the @Repository annotation in the Spring Framework is a marker for any class that fulfills the role or stereotype of a repository (also known as Data Access Object or DAO).

@Component is a generic stereotype for any Spring-managed component. Any component annotated with @Component is a candidate for component scanning. Similarly, any component annotated with an annotation that is itself meta-annotated with @Component is also a candidate for component scanning. For example, @Service is meta-annotated with @Component.

Core Spring provides several stereotype annotations out of the box, including but not limited to: @Component, @Service, @Repository, @Controller, @RestController, and @Configuration. @Repository, @Service, etc. are specializations of @Component.

模式注解是一种用于声明在应用中扮演“组件”角色的注解。如 Spring Framework 中的 @Repository 标注在任何类上 ,用于扮演仓储角色的模式注解。
@Component 作为一种由 Spring 容器托管的通用模式组件,任何被 @Component 标准的组件均为组件扫描的候选对象。类似的,凡是被 @Component 元标注(meta-annotated)的注解,如 @Service ,当任何组件标注它时,也被视作组件扫描的候选对象。

模式注解举例:

Spring Framework 注解场景说明起始版本
@Repository数据仓库模式注解2.0
@Component通用组件模式注解2.5
@Service服务模式注解2.5
@ControllerWeb 控制器模式注解2.5
@Configuration配置类模式注解3.0

3.装配方式

<context:component-scan …> 方式

<?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
        https://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 或者其派生注解标记的类,将它们注册为 Spring Bean -->
    <context:component-scan base-package="com.huajie.deepinspringboot"/>

</beans>

@ComponentScan 方式

@ComponentScan(basePackages = "com.huajie.deepinspringboot")
public class SpringConfiguration {
      ...
}

在 SpringBoot 场景中 @SpringBootApplication 启动类的注解已经包含了这个 @ComponentScan 注解。

4.自定义模式注解

4.1 @Component “派生性”

新建 @FirstLevelRepository 使用 @Repository 进行元标注

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repository
public @interface FirstLevelRepository {
    // 方法签名保持一致
    String value() default "";

}

层次关系:@Component -> @Repository -> @FirstLevelRepository

测试:

新建 MyFirstLevelRepository 使用 @FirstLevelRepository 进行标注

@FirstLevelRepository("myFirstLevelRepository")
public class MyFirstLevelRepository {
}

测试引导类

@SpringBootApplication(scanBasePackages = "com.huajie.deepinspringboot.repository")
public class RepositoryBootstrap {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(RepositoryBootstrap.class)
                .web(WebApplicationType.NONE)
                .run(args);

        MyFirstLevelRepository bean = context.getBean("myFirstLevelRepository", MyFirstLevelRepository.class);
        System.out.println(bean);
        context.close();
    }
}

执行结果:

com.huajie.deepinspringboot.repository.MyFirstLevelRepository@187eb9a8

可以看到被我们自定义注解标注的 MyFirstLevelRepository 类已经被扫描 Spring IoC 中,这就是@Component 注解的“派生性”。

4.2 @Component “层次性”

新建 @SecondLevelRepository 使用 @FirstLevelRepository 进行元标注

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@FirstLevelRepository
public @interface SecondLevelRepository {
    // 方法签名保持一致
    String value() default "";

}

层次关系:@Component -> @Repository -> @FirstLevelRepository -> @SecondLevelRepository

新建 MySecondLevelRepository 使用 @SecondLevelRepository 进行标注

@SecondLevelRepository("mySecondLevelRepository")
public class MySecondLevelRepository {
}

测试引导类

@SpringBootApplication(scanBasePackages = "com.huajie.deepinspringboot.repository")
public class RepositoryBootstrap {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(RepositoryBootstrap.class)
                .web(WebApplicationType.NONE)
                .run(args);

        MyFirstLevelRepository bean = context.getBean("myFirstLevelRepository", MyFirstLevelRepository.class);

        MySecondLevelRepository bean2 = context.getBean("mySecondLevelRepository", MySecondLevelRepository.class);

        System.out.println(bean);
        System.out.println(bean2);
        context.close();
    }
}

执行结果:

com.huajie.deepinspringboot.repository.MyFirstLevelRepository@13d186db
com.huajie.deepinspringboot.repository.MySecondLevelRepository@6f6962ba

虽然 @SecondLevelRepository 没有直接被 @Component 标注,但是 @SecondLevelRepository 和 @FirstLevelRepository 效果类似,这就是@Component 注解的“层次性”。

4.3 @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

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

}

@Configuration

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

}

层次关系:@Component -> @Configuration-> @SpringBootConfiguration -> @SpringBootApplication

在 Spring Boot 场景中,@SpringBootApplication 也是模式注解。

5.参考

  • 慕课网-小马哥《Spring Boot2.0深度实践之核心技术篇》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值