文章目录
一、 前言
在springBoot项目中,我们会发现有各种starter(redis、nacos、mybaits等),我们需要用mybaits,只需引入对应的starter,然后springBoot会自动装配对应的bean到spring容器中。我们直接使用即可,同时会有一些配置,我们可以根据自己的实际情况配置。
springBoot如何装配所需的类?在实际开发中,我们如何自定义starter呢?本文章将从这两点讲述starter。
二、 springBoot如何装配对应的bean
首先,我们需要了解一个注解:@SpringBootApplication
。在一个springBoot项目中,我们在启动类上都会加上@SpringBootApplication
这个注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
我们会发现,这个注解相当于@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
- @SpringBootConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
@SpringBootConfiguration继承自@Configuration,二者功能也一致,标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到spring容器中,并且实例名就是方法名。
- @ComponentScan
这个类就不用解释,他会讲对应的扫描包下的含有相应注解(@Controller、@Service、@RestController、@Component、@configure、@Repository,简而言之就是含有@Component注解)的类注册到spring容器中 - @EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
进入@Import(AutoConfigurationImportSelector.class)
对应的类->selectImports
->getAutoConfigurationEntry
->getCandidateConfigurations
->loadFactoryNames,我们会发现,他会加载META_INF/spring.facotories中的读取,然后以健值对的形式返回,然后在通过各种条件注解
解决类是否装配到容器中。
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
下图是读取spring.facotories文件,然后返回自动装配类的方法
下图是redis自动装配的类
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
三、自定义starter
3.1 创建springBoot工程,引入依赖
注意artifactId为xx-spring-boot-starter
,同时需要引入下边的依赖到项目中
<!--自定义starter必须要引入的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
3.2 定义相关类
3.2.1 定义配置属性
/**
* @author luyi
* starter对应demo的配置属性
*/
@ConfigurationProperties(prefix = "spring.starter",ignoreInvalidFields = true)
public class DemoProperties {
private String name="luyi";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.2.2 定义业务以及实现类
/**
* @author luyi
*/
public interface StarterDemo {
void welcome();
}
/**
* @author luyi
* 定义实现类
*
*/
public class StarterDemoImpl implements StarterDemo {
@Autowired
private DemoProperties demoProperties;
@Override
public void welcome() {
System.out.println(demoProperties.getName()+",欢迎啦");
}
}
3.2.3 定义配置类
/**
* @author luyi
* 自动配置demo类
*/
@Configuration
@ConditionalOnClass
@EnableConfigurationProperties(DemoProperties.class)
public class DemoAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public StarterDemoImpl initDemoImpl(){
return new StarterDemoImpl();
}
}
3.3 配置spring.factories
在resources下新建META-INF目录,并在这个目录下添加spring.factories文件,并增加配置
#=后边的根据实际情况配置类的全路径
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.ly.starter.DemoAutoConfiguration
3.4 安装install
我们可以用mvn clean install,或者maven选项的安装
安装完成后,我们会发现本地的maven仓库中会有对应的依赖
3.5 使用
像平时引入其他的starter一样即可。
@SpringBootApplication
//@EnableScheduling//开启定时
public class TimerApplication implements CommandLineRunner {
@Autowired
private StarterDemo starterDemo;
public static void main(String[] args) {
SpringApplication.run(TimerApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
starterDemo.welcome();
}
}
我们在yml中配置如下:,启动项目
spring:
starter:
name: test
控制台输出如下,说明我们starter成功啦