场景:在微服务项目中,或者在一些项目,例如在一个网站中的消息提示、聊天机器人等功能场景中,它相当于是一个公共的功能,在所有模块中都需要,这时候我们肯定不能把代码各复制一份给每个功能模块,这时候就要抽取一个公共模块,也就是自定义starter
效果:任何项目导入此starter都具有打招呼功能,并且问候语中的人名需要可以在配置文件中修改

  1. 创建自定义starter项目,引入spring-boot-starter基础依赖
  2. 编写模块功能,引入模块所有需要的依赖。
  3. 编写xxxAutoConfiguration自动配置类,帮其他项目导入这个模块需要的所有组件
  4. 编写配置文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports指定启动需要加载的自动配置
  5. 其他项目引入即可使用

以上是大概的流程,现在有三种方式来进行自定义starter,由麻烦到简单的方法。

1.业务代码

首先创建一个properties的类来连接与properties配置文件进行bean连接

@Data
@Component
@ConfigurationProperties(prefix = "robot")
public class RobotProperties {
    private String name;
    private int age;
    private String email;
}

自定义配置没有提示。导入以下依赖重启项目,再写配置文件就有提示

<!--        导入配置处理器,配置文件自定义的properties配置都会有提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
robot.name=代浩楠
robot.age=24
robot.email=913219642@qq.com

创建一个service

@Service
public class RobotService {
    @Autowired
    RobotProperties robotProperties;

    public String sayHello(){
        return "你好:名字:["+robotProperties.getName()+"],年龄:["+robotProperties.getAge()+"]";
    }
}

再创建一个controller进行调用

@RestController
@RequestMapping("robot")
public class RobotController {

    @Autowired
    private RobotService robotService;

    @GetMapping("hello")
    public String hello(){
        return robotService.sayHello();
    }

}

2.基本抽取

  • 创建starter项目,把公共代码需要的所有依赖导入
  • 把公共代码复制进来
  • 自己写一个 RobotAutoConfiguration,给容器中导入这个场景需要的所有组件
  • 别人引用这个starter,直接导入这个 RobotAutoConfiguration,就能把这个场景的组件导入进来
  • 功能生效。
  • 测试编写配置文件

这个遇到的一个问题是我们导入了新模块的pom依赖了,为什么这些组件默认不会扫描进去呢?
因为starter所在的包和引入它的项目的主程序所在的包不是父子层级,比如我的原始项目的层级在**com/dhnsoft/boot/core/Boot307CoreApplication.java**,抽取的新starter的层级在**com/dhnsoft/boot3/starter/RobotAutoConfiguration.java**,这两个层级不在一个里面的话就扫描不到组件,需要使用**@import**来扫描进来。

1.首先我创建了一个新的项目模块,里面包含了之前创建的那些代码

springboot 共通配置文件 springboot公共模块_spring boot


2.在其他功能模块中引用新项目模块的pom依赖

<dependency>
			<groupId>com.dhnsoft</groupId>
			<artifactId>boot3-08-robot-starter</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

3.在新项目模块的根目录创建一个xxxAutoConfiguration.java

这个类中的配置有两种方式:
1.可以使用@Import来把需要公共输出的功能模块给加载到组件中
2.也可以使用@Bean来将功能代码给加载到组件中

@Import({RobotService.class, RobotProperties.class})
//@Import({RobotController.class, RobotService.class, RobotProperties.class})
@Configuration
public class RobotAutoConfiguration {

    @Bean
    public RobotController robotController(){
        return new RobotController();
    }
}

4.最后在之前的功能模块中的启动类上直接使用@Import注解来引用新模块的公共功能
@Import(RobotAutoConfiguration.class)

3.使用@EnableXxx机制

以上使用@import还是有点麻烦,我们可以自定义注解来进行抽取

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RobotAutoConfiguration.class)
public @interface EnableRobot {
}

然后直接在其他功能模块的启动类上标上@EnableRobot注解

4.完全自动配置

  • 依赖SpringBoot的SPI机制
  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中编写好我们自动配置类的全类名即可
  • 项目启动,自动加载我们的自动配置类

自己在resources下自己创建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

springboot 共通配置文件 springboot公共模块_spring_02


在里面填入新模块功能的哪个配置类就行了,这样就也不用注解了,直接把pom依赖引入到其他功能模块就可以了

springboot 共通配置文件 springboot公共模块_java_03