美文网首页
SpringBoot自定义场景启动器(starter)

SpringBoot自定义场景启动器(starter)

作者: Wannay | 来源:发表于2021-07-28 04:39 被阅读0次

    1.场景启动器的原理是什么?

    xxx-spring-boot-starter的作用是负责导入xxx-spring-boot-starter-autoconfigure的依赖,而场景启动器真正的逻辑其实都在xxx-spring-boot-starter-autoconfigure当中。

    xxx-spring-boot-starter-autoconfigure中会使用一个XXXProperties的类去绑定application.yaml或者application.properties中的某个前缀的配置,并将该组件导入到容器当中。这样后续我们想要配置文件中的内容,只需要从容器中拿到这个类就可以拿到相关的配置。

    XXXAutoConfiguration配置类负责给容器中导入相应的组件,一般使用条件装配的方式进行导入,也就是如果用户自定义了相关的组件,那么我们就不导入相关的组件,而如果我们没有自定义相关的组件,那么容器中就通过配置文件的配置信息(XXXProperties),给容器中装配一个组件。

    比如我们来看Spring-Data-Redis的自动装配:

    image.png

    2.开始自定义场景启动器

    2.1 创建一个项目test,并建立两个模块

    两个模块一般叫xxx-spring-boot-starterxxx-spring-boot-starter-autoconfigure

    image.png

    2.2 引入相关依赖

    xxx-spring-boot-starter里引入xxx-spring-boot-starter-autoconfigure的依赖

        <dependencies>
            <dependency>
                <groupId>com.wanna</groupId>
                <artifactId>wanna-spring-boot-starter-autoconfigure</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>
        </dependencies>
    

    xxx-spring-boot-starter-autoconfigure中引入spring-boot-starter的依赖

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
        </dependencies>
    

    2.3 开始编写代码

    xxx-spring-boot-starter中什么都不做...只需要写xxx-spring-boot-starter-autoconfigure的逻辑

    编写一个HelloService类,简单逻辑:给输入的name参数,加上指定的前缀/后缀并进行输出的sayHello方法

    public class HelloService {  //默认不要放在容器中,使用条件装配进行装配
        private HelloProperties helloProperties;
    
        public String sayHello(String name) {
            return helloProperties.getPrefix() + ":" + name + ">>>" + helloProperties.getSuffix() + "!";
        }
    
        public HelloProperties getHelloProperties() {
            return helloProperties;
        }
    
        public void setHelloProperties(HelloProperties helloProperties) {
            this.helloProperties = helloProperties;
        }
    }
    

    需要注意的是,这个组件默认不要放在容器中!需要通过配置类进行条件装配!HelloProperties的建立见下文,它的主要作用是和配置文件中指定前缀的配置进行绑定。

    @ConfigurationProperties(prefix = "wanna.hello")
    public class HelloProperties {
        private String prefix;
        private String suffix;
    
        public String getSuffix() {
            return suffix;
        }
    
        public void setSuffix(String suffix) {
            this.suffix = suffix;
        }
    
        public String getPrefix() {
            return prefix;
        }
    
        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }
    }
    

    下面就到了关键环节,编写一个自动配置类,一般叫XXXAutoConfiguration

    @Configuration
    @EnableConfigurationProperties(HelloProperties.class)  //开启配置注解,这个组件中的所有属性将从配置文件中获取,并把组件放到容器中
    public class HelloServiceAutoConfiguration {
    
        @Bean
        @ConditionalOnMissingBean({HelloService.class})  //在容器中缺少这个Bean的时候才往容器中注入,如果容器中已经有了就不用注入了
        public HelloService helloService(@Autowired HelloProperties helloProperties) {
            HelloService helloService = new HelloService();
            helloService.setHelloProperties(helloProperties);
            return helloService;
        }
    }
    

    使用@EnableConfigurationProperties注解开启属性绑定,将配置文件中指定前缀的配置文件和HelloProperties进行绑定(绑定配置文件的类一般叫XXXProperties)。并使用@ConditionalOnMissingBean注解标明,只有在缺少我们自定义的Bean的时候才将该组件导入到容器当中。

    完成了代码的编写之后,我们需要完成的是,需要往容器中导入哪些自动配置类的相关配置:

    image.png

    在resources文件夹下建立META-INF文件夹,建立一个spring.factories配置文件
    往其中添加如下内容,用来标明我们想要往容器中导入的XXXAutuConfiguration组件的全类名

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.wanna.hello.auto.HelloServiceAutoConfiguration
    

    2.4 打包进maven本地仓库

    依次完成xxx-spring-boot-starter-autoconfigurexxx-spring-boot-starter模块的打包,就放到我们maven本地仓库当中。

    image.png

    2.5 重新创建一个项目进行测试

    引入我们刚刚打包好的xxx-spring-boot-starter的依赖(并且引入Web的场景启动器方便进行测试)

            <dependency>
                <groupId>com.wanna</groupId>
                <artifactId>wanna-spring-boot-starter</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    

    编写application.yaml或者application.properties配置文件,配置我们自动装配包中需要提供的前缀的配置:

    wanna.hello.prefix=hello
    wanna.hello.suffix=666
    

    编写测试的Controller

     @RestController
    public class HelloController {
    
        HelloService helloService;
    
        @Autowired
        public HelloController(HelloService helloService) {
            this.helloService = helloService;
        }
    
        @RequestMapping("/sayHello/{name}")
        public String sayHello(@PathVariable("name") String name) {
            return helloService.sayHello(name);
        }
    }
    

    在浏览器中进行测试:

    image.png

    发现装配成功,既然是条件装配我们自然还得测试自己自定义给容器中导入一个 HelloService能否成功?下面编写一个Spring的配置类:

    @Configuration
    public class Config {
    
        @Bean
        public HelloService helloService() {
            HelloService helloService = new HelloService();
            HelloProperties properties = new HelloProperties();
            properties.setPrefix("666");
            properties.setSuffix("777");
            helloService.setHelloProperties(properties);
            return helloService;
        }
    }
    

    在浏览器中进行测试:

    image.png

    我们发现我们做到了条件装配,如果我们自己往容器中导入了相关的组件,那么自动配置类就不会导入相关的组件,而如果我们没配置,那么场景启动器会帮我们自动导入相关的组件。

    相关文章

      网友评论

          本文标题:SpringBoot自定义场景启动器(starter)

          本文链接:https://www.haomeiwen.com/subject/ceiamltx.html