SpringBootStarter的定义方式

Catalogue
  1. 定义AutoConfiguration
    1. 一. 常用注解
      1. 1. Configuration
      2. 2. EnableConfigurationProperties
      3. 3. Conditional
      4. 4. ConditionalXXXX
    2. 二. 两种方式集成方式
      1. 1. 主动生效
      2. 2. 被动生效
      3. 3. 优缺点
    3. 三.命名规范

定义AutoConfiguration

一. 常用注解

1. Configuration

用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

和xml配置一样,可以配置Bean的生命周期中的各个方法。

1
@Bean(name="testBean",initMethod="start",destroyMethod="stop")

问题1:加了Configuration后,怎么将想要的Bean加载到应用的Spring容器中呢?

  • 可以想想之前xml的bean配置文件怎么加载的。
1
2
3
4
5
6
7
8
9
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
...
}

FileSystemXmlApplicationContext
ClassPathXmlApplicationContext
EmbeddedWebApplicationContext
GroovyWebApplicationContext
AnnotationConfigApplicationContext

也就是在初始化以上各个ApplicationContext的时候,会加载指定的Configuration, 不管是xml还是注解方式的。

那Configuration配置的Bean的加载方式就是可以通过AnnotationConfigApplicationContext。
ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);

问题2: Configuration的配置类在做一些组件的时候怎么定义,来实现组件的灵活性

这个问题如果了解一些初始化ApplicationContext的时候对Configuration的识别加载流程可能更容易理解。TODO.

另外,在@configuration中还可以引入其它注解配置

1
2
@ImportResource("classpath:applicationContext-configuration.xml")
@Import(TestConfiguration.class)

主要作用理解为是将相关的Bean加载到Spring容器。

2. EnableConfigurationProperties

@EnableConfigurationProperties注解的作用是:使使用 @ConfigurationProperties 注解的类生效。

如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component,那么在IOC容器中是获取不到properties 配置文件转化的bean。

@EnableConfigurationProperties 相当于把使用 @ConfigurationProperties 的类进行了一次注入。

当@EnableConfigurationProperties注解应用到@Configuration时, 任何被@ConfigurationProperties注解的beans将自动被Environment属性配置。 这种风格的配置特别适合与SpringApplication的外部YAML配置进行配合使用。

感觉和@Component的功能类似。将属性配置类注入到容器。

3. Conditional

Spring4推出了@Conditional注解,方便程序根据当前环境或者容器情况来动态注入bean.

继@Conditional注解后,又基于此注解推出了很多派生注解,比如@ConditionalOnBean、@ConditionalOnMissingBean、@ConditionalOnExpression、@ConditionalOnClass……实现动态注入bean

ConditionalOnClass 自动配置的重要支撑之一。判断当前classpath下是否存在指定类,若是则将当前的配置装载入spring容器。

但这个还不会熟练使用。只是理解了大概是这个意思。

1
2
@ConditionalOnClass(JsonRedisTemplate.class)
public class LinkWhiteListRedisOps{}

如果classpath存在JsonRedisTemplate的情况下,则将LinkWhiteListRedisOps装载到spring容器。

4. ConditionalXXXX

  • @ConditionalOnBean 当指定一个Bean存在是,才创建当前这个Bean
  • @ConditionalOnMissingBean 当指定Bean不存在是,才创建这个Bean.
  • @ConditionalOnProperty来控制Configuration是否生效

Class的存在与否作为条件。

从使用来看,和前面基本上没有太大的区别,无非就是将bean换成了class;这样就可以避免因为Class Not Found导致的编译异常了。

如提供了一个bean名为RedisOperBean,用于封装redis相关的操作;但是我这个bean需要依赖restTemplate这个bean,只有当应用引入了redis的相关依赖,并存在RestTemplate这个bean的时候,我这个bean才会生效.

1
2
3
4
5
6
7
8
@Component
@ConditionalOnBean(name="redisTemplate")
public class RedisOperBean {
private final RedisTemplate redisTemplate;
public RedisOperBean(RedisTemplate redisTemplate) {
// ...
}
}

springboot注解丰富,我们可以利用好这些注解来实现我们自定义的starter配置,减少硬编码的校验,降低组件间的耦合性!!!

二. 两种方式集成方式

主动生效和被动生效

从使用者的角度。

1. 主动生效

使用@Import注解。主动声明启用该starter才生效。比如加到我们的启动来,或者将该注解标记到你自定义的@Enable注解上。

1
2
3
4
5
6
@Target(ElementType.TYPE)
@Documented
@Import(RedisToolsAutoConfiguration.class)
public @interface EnableRedisTools{

}

2. 被动生效

在starter组件集成入SpringBoot应用时,就已经被应用捕捉到。类似java的SPI机制。

新建 META-INF/spring.factories文件。
写入AutoConfiguration全限定名。

1
2
3
# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
ch.quiz.redis.distributed.config.RedisLimitAutoConfiguration

3. 优缺点

  1. 主动生效的方式需要在使用的项目中手动指定,enable. 也属于硬编码。而相对被动生效。我们可以通过配置来实现组件的生效。

  2. 被动生效虽然可以通过配置来控制组件生效,但AutoConfiguration中配置的一些组件对象会实例到容器。
    比如redis连接,不管是否生效,他都会在实例化的时候连接默认的redis.如果不适用,实例化就是有些浪费。

三.命名规范

Spring官方Starter通常命名为spring-boot-starter-{name}如 spring-boot-starter-web

Spring官方建议非官方Starter命名应遵循{name}-spring-boot-starter的格式, 如mybatis-spring-boot-starter。