共计 5210 个字符,预计需要花费 14 分钟才能阅读完成。
作者:谭淼
一、运行原理
Spring Boot 的运行是由注解 @EnableAutoConfiguration 提供的。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = “spring.boot.enableautoconfiguration”;
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
这里的关键功能是 @Import 注解。EnableAutoConfigurationImportSelector 使用 SpringFactoriesLoader.loadFactoryNames 方法来扫描具有 MEAT-INF/spring.factories 文件的 jar 包(1.5 版本以前使用 EnableAutoConfigurationImportSelector 类,1.5 以后这个类废弃了使用的是 AutoConfigurationImportSelector 类),下面是 spring-boot-autoconfigure-1.5.4.RELEASE.jar 下的 MEAT-INF 中的 spring.factories 文件的部分内容。
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
里面的类都是自动配置类,SpringBoot 会根据这些自动配置类去自动配置环境。
下面我们就自动动手写一个 starter。
二、自定义 Starter
首先先介绍几个条件注解。
@ConditionalOnBean:当容器里有指定的 Bean 为 true
@ConditionalOnClass:当类路径下有指定的类为 true
@ConditionalOnMissingBean:当容器里没有指定的 Bean 为 true
@ConditionalOnProperty:指定的数据是否有指定的值
…
了解了条件注解后,我们开始自定义 Starter。
1、在自定义 Starter 之前先要在 Maven 中填写依赖。
<?xml version=”1.0″ encoding=”UTF-8″?>
<project xmlns=”http://maven.apache.org/POM/4.0.0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
<modelVersion>4.0.0</modelVersion>
<groupId>cn.miaolovezhen</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-starter-test</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/> <!– lookup parent from repository –>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>1.5.4.RELEASE</version>
</dependency>
</dependencies>
</project>
2、完成 TestProperties 类,这个类定义了默认的属性值,如该类中,只有一个属性值 msg,默认为 world。@ConfigurationProperties 注解会定义一个匹配,如果想修改属性值,可以在 application.properties 中使用“匹配. 属性 = 修改的值”进行修改。如 test.msg = tan
@ConfigurationProperties(prefix = “test”)
public class TestProperties {
private static final String MSG = “springboot”;
private String msg = MSG;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
3、完成服务类。服务类是指主要的功能类,如果没有 SpringBoot,这些服务类在 Spring 中都是需要自己去配置生成的。如 SpringMVC 中的 DispatcherServlet、Mybatis 的 DataSource 等。
public class TestService {
private String msg;
public String sayHello(){
return “Hello ” + msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
4、完成自动配置类。自动配置类主要作用是 SpringBoot 的配置核心,它会写在 MEAT-INF/spring.factories 中,告知 SpringBoot 在启动时去读取该类并根据该类的规则进行配置。
@EnableConfigurationProperties 注解根据 TestProperties 类开启属性注入,允许在 application.properties 修改里面的属性值。
@ConditionOnClass 会检测是否存在 TestService 类
@ConditionOnProperty 类会查看是否开启该自动配置。默认开启(true)。
@ConditionOnMissingBean 会检测容器中是否有 TestService 类的对象,如果没有则生成一个。
@Configuration
@EnableConfigurationProperties(TestProperties.class)
@ConditionalOnClass(TestService.class)
@ConditionalOnProperty(prefix = “test” , value = “enabled” , matchIfMissing = true)
public class TestServiceAutoConfiguration {
@Autowired
TestProperties testProperties;
@Bean
@ConditionalOnMissingBean(TestService.class)
public TestService testService(){
TestService testService = new TestService();
testService.setMsg(testProperties.getMsg());
return testService;
}
}
5、最后一步,不要忘记在在 MEAT-INF 文件夹中创建 spring.factories 文件。内容很简单,告诉 SpringBoot 去读取 TestServiceAutoConfiguration 类。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.miaolovezhen.TestServiceAutoConfiguration
好啦,搞定!下面可以使用 maven install 命令把 starter 存到本地,其他 SpringBoot 项目需要使用这个 starter,直接导入就可以啦。
参考:《java EE 开发的颠覆者:springboot 实战》