加入收藏 | 设为首页 |

作息时间表-Spring Boot 自定义Starter

海外新闻 时间: 浏览:259 次

本号首要用于共享企业中常用的技能,愈加侧重于有用,欢迎重视,便于阅读其它更多有用的历史文章。

在springboot中,运用的最多的便是starter。starter能够理解为一个可拔插式的插件,例如,你想运用jdbc插件,那么能够运用spring-boot-starter-jdbc;假如想运用mongodb,能够运用spring-boot-starter-data-mongodb。 自界说starter

  • 自界说starter
  • 运用starter

1. 创立一个maven工程(maven-archetype-quickstart)

留意artifactId的命名规矩,Spring官方Starter一般命名为spring-boot-starter-{name}如 spring-boot-starter-web, Spring官方主张非官方Starter命名应遵从{name}-spring-boot-starter的格局, 如mybatis-spring-boot-starter。这儿创立的项目的artifactId为helloworld-spring-boot-starter

2. 引进必要的依靠

留意:这儿的packaging为jar,starter需求运用到Spring boot的主动装备功用,所以需求引进主动装备相关的依靠

com.mengday
helloworld-spring-boot-starter
1.0-SNAPSHOT
jar


org.springframework.boot
spring-boot-autoconfigure
2.0.0.RELEASE


org.springframework.boot
spring-boot-configuration-processor
2.0.0.RELEASE
true


3. XxxProperties

在运用Spring官方的Starter时一般能够在application.properties中来装备参数覆盖掉默许的值,例如在运用redi作息时间表-Spring Boot 自定义Starters时一般就会有对应的RedisProperties

@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
private int database = 0;
private String url;
private String host = "localhost";
private String password;
private int port = 6379;
}
咱们来仿照来界说自己的Properties类
@ConfigurationProperties(prefix = "spring.person")
public class PersonProperties {
// 名字
private String name;
// 年纪
private int age;
// 性别
private String sex = "M";

// Getter & Setter
}

4. 中心服务类

每个starter都有自己的功用,例如在spring-boot-starter-jdbc中最重要的类时JdbcTemplate,每个starter中的中心事务类理解都不同,也没什么规矩(像spring-boot-starter-data-xxx的命名是比较有规矩的),这儿运用PersonService来界说helloworld-spring-boot-starter的功用,这儿经过一个sayHello来模仿一个功用。

public class PersonService {
private PersonProperties properties;
public PersonService() {
}
public PersonService(PersonProperties properties) {
this.properties = properties;
}

public void sayHello(){
System.out.println("大家好,我叫: " + properties.getName() + ", 本年" + properties.getAge() + "岁"
+ ", 性别: " + properties.getSex());
}
}

5. 主动装备类

一般每个starter都至少会有一个主动装备类,一般命名规矩运用XxxAutoConfiguration, 例如RedisAutoConfiguration

@Configuration
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfiguration {
@Configuration
@ConditionalOnClass(GenericObjectPool.class)
protected static class RedisConnectionConfiguration {
private final RedisProperties properties;

@Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
public JedisConnectionFactory redis作息时间表-Spring Boot 自定义StarterConnectionFactory()
throws UnknownHostException {
return applyProperties(createJedisConnectionFactory());
}
}
@Configuration
protected static class RedisConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}

这儿咱们界说自己的主动装备PersonServiceAutoConfiguration,并将中心功用类PersonService放入到Spring Context容器中

@Configuration
@EnableConfigurationProperties(PersonProperties.class)
@ConditionalOnClass(PersonService.class)
@ConditionalOnProperty(prefix = "spring.person", value = "enabled", matchIfMissing = true)
public class PersonServiceAutoConfiguration {
@Autowired
private PersonProperties properties;
@Bean
@ConditionalOnMissingBean(PersonService.class) // 当容器中没有指定Bean的情况下,主动装备PersonService类
public PersonService personService(){
Person作息时间表-Spring Boot 自定义StarterService personService = new PersonService(properties);
return personService;
}
}
  • @ConditionalOnClass:当类途径classpath下有指定的类的情况下进行主动装备
  • @ConditionalOnMissingBean:当容器(Spring Context)中没有指定Bean的情况下进行主动装备
  • @ConditionalOnProperty(prefix = “example.service”, value = “enabled”, matchIfMissing = true),当装备文件中example.service.enabled=true时进行主动装备,假如没有设置此值就默许运用matchIfMissing对应的值
  • @ConditionalOnMissingBean,当Spring Context中不存在该Bean时。
  • @ConditionalOnBean:当容器(Spring Context)中有指定的Bean的条件下
  • @ConditionalOnMissingClass:当类途径下没有指定的类的条件下
  • @ConditionalOnExpression:根据SpEL表达式作为判别条件
  • @ConditionalOnJava:根据JVM版别作为判别条件
  • @ConditionalOnJndi:在JNDI存在的条件下查找指定的方位
  • @ConditionalOnNotWebApplication:当时项目不是Web项目的条件下
  • @ConditionalOnWebApplication:当时项目是Web项目的条件下
  • @ConditionalOnResource:类途径下是否有指定的资源
  • @ConditionalOnSingleCandidate:当指定的Bean在容器中只要一个,或许在有多个Bean的情况下,用来指定首选的Bean

6.src/main/resources/META-INF/spring.factories

留意:META-INF是自己手动创立的目录,spring.factories也是手动创立的文件,在该文件中装备自己的主动装备类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.mengday.helloworld.PersonServiceAutoConf

7. 打包mvn clean install

8. 创立一个Spring Boot工程并引进依靠


com.mengday
helloworld-spring-boot-starter
1.0-SNAPSHOT

9.装备application.properties

spring.person.name=mengday
spring.person.age=28

10.test

import com.mengday.helloworld.PersonService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MystarterApplicationTests {
@Autowired
private PersonService personService;
@Test
public void testHelloWorld() {
personService.sayHello();
}
}

从运用者的视点来看,自己并没有将PersonService放入到Spring容器中,就直接来运用了,进行注入进来了。

总结下Starter的作业原理

  1. Spring Boot在启动时扫描项目所依靠的JAR包,寻觅包括spring.factories文件的JAR包,
  2. 然后读取spring.factories文件获取装备的主动装备类AutoConfiguration,
  3. 然后将主动装备类下满意条件(@ConditionalOnXxx)的@Bean放入到Spring容器中(Spring Context)
  4. 这样运用者就能够直接用来注入,由于该类已经在容器中了

  1. @ConfigurationProperties: 注解首要用来把properties装备文件转化为对应的XxxProperties来运用的,并不会把该类放入到IOC容器中,假如想放入到容器中能够在XxxProperties上运用@Component来标示,也能够运用@EnableConfigurationProperties(XxxProperties.class)一致装备到Application上来,这种方法能够在Application上来一致敞开指定的特点,这样也没必要在每个XxxProperties上运用@Component
  2. @EnableConfigurationProperties(XxxProperties.class) 注解的作用是@ConfigurationProperties注解收效。假如只装备@ConfigurationProperties注解,在IOC容器中是获取不到properties装备文件转化的bean的
local.host=127.0.0.1
local.port=8080
dev.host=192.168.0.1
dev.port=8888
@ConfigurationProperties(prefix="local")
public class LocalProperties {
战国策private String host;
private String port;
}
@ConfigurationProperties(prefix="dev")
public class DevProperties {
private String host;
private String port;
}
@SpringBootApplication
@EnableConfigurationProperties({LocalProperties.class, DevProperties.class})
public class MystarterApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(MystarterApplication作息时间表-Spring Boot 自定义Starter.class, args);
System.out.println(applicationContext.getBean(LocalProperties.class));
System.out.println(applicationContext.getBean(DevProperties.class));
applicationContext.close();
}
}

假如在每个Properties上都运用@Component来标示,那么在XxxApplication上也不需求运用@EnableConfigurationProperties({XxxProperties.class})来标示了,相同也能够在spring上下文容器中也能获取到XxxProperties对应的bean

本号首要用于共享企业中常用的技能,愈加侧重于有用,欢迎重视,便于阅读其它更多有用的历史文章。