SpringBoot自定义starter方式
作者:Exill
命名
推荐以xxx-spring-boot-starter命名
原理
引入spring-boot-starter-jdbc后可直接使用DataSource
1.加载自动配置类
通过SPI(Service Provider Interface,Java提供的服务发现机制,用于框架拓展和组件替换)原理
(1)@SpringBootApplication->@EnableAutoConfiguration->@Import
(2)@Import通过AutoConfigurationImportSelector::selectImports方法导入自动配置类
(3)在AutoConfigurationImportSelector::getCandidateConfigurations方法中得知导入的自动配置类在从META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件读取
(4)其中包含DataSourceAutoConfiguration类
2.通过xxxAutoConfiguration再导入功能所需的bean
(1)
DataSourceAutoConfiguration->@EnableConfigurationProperties(DataSourceProperties.class)
将Properties类生效,读取application.yml中数据(url、username、password...)
(2)
@Import({ DataSourceConfiguration.Hikari.class... })
导入各种连接池,根据条件注解生效不同连接池
自定义starter
示例:@Log的添加日志功能封装成starter
1.创建标准SpringBoot项目引入所需依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
2.编写Properties类
@Data @Component @ConfigurationProperties("log") public class LogProperties{ private Boolean classFullName= true; //日志展示全类名 private Boolean showUseTime= true; //日志展示方法执行时间 }
3.编写application.yml配置文件
log: class-full-name: true #展示全类名 show-use-time: true #展示方法执行时间
4.编写@Log注解
@Target(METHOD) //该注解只能用于方法上 @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface Log{}
5.编写AOP实现具体功能
@Slf4j @Aspect @Component public class LogAop { @Resource private LogProperties logProperties; @Around("@annotation(com.gok.log.annotation.Log)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { long beginTime = System.currentTimeMillis(); Class targetClass = joinPoint.getSignature().getDeclaringType(); String functionName = joinPoint.getSignature().getName(); String name = (logProperties.getClassFullName() ? targetClass.getName() : targetClass.getSimpleName()) + "#" + functionName; try { log.info("{}开始", name); Object res = joinPoint.proceed(joinPoint.getArgs()); log.info("{}结束", name); return res; } catch (Throwable t) { log.info("{}异常," + t.getMessage(), name); throw t; } finally { if (logProperties.getShowUseTime()) { log.info("{}执行时间:{}ms", name, System.currentTimeMillis() - beginTime); } } } }
SpringBoot默认只扫描启动类所在目录,而Log实现所在的包不会扫描,有@Component也无效
所以通过原理中的SPI机制导入
6.删除LogProperties类和LogAop类的@Component注解
统一在LogAutoConfiguration导入
@Configuration //引入Properties类 @EnableConfigurationProperties(LogProperties.class) //引入Aop @Import(LogAop.class) public class LogAutoConfiguration { }
7.编写文件
编写META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
引入自动配置类com.gok.logstarter.config.LogAutoConfiguration
8.删除SpringBoot启动类(main方法所在类)、删除pom.xml<build>标签
原因:作为starter不需要启动类
9.补充
(1)自定义starter的application.yml可以删除,最终生效的是引入starter项目中application.yml
(2)如果希望实现编写application.yml文件智能提示,需要在自定义starter的pom.xml添加如下依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。