SpringBoot启动类大家都不陌生,只要在main方法上增加一个@SpringBootApplication注解,就可以启动了。
我们点开该注解
其中关键注解为@EnableAutoConfiguration,再次跟进
其中引入了EnableAutoConfigurationImportSelector.class,解释见下图
其中关键的方法为getCondidateConfiguration(metadata attributes)
中的SpringFactoriesLoader.loadFactoryNames(..)方法。
SpringFactoriesLoader默认查找的位置就是”META-INF/spring.factories”,而在spring-boot-autoconfigure-1.4.7.jar中就有一个spring.factories。在其中配置了各种各样的AutoConfigure类。到了这一步,我们算是找到了springBoot启动时自动配置的源头。就是在spring.factories中我们通过org.springframework.boot.autoconfigure.EnableAutoConfiguration配置的启动时自动加载的自动配置类。所有的自动配置类采用了Spring4.0+的JAVA配置方法(即@Configuration+@Bean)进行配置
现在我们手写一个自动配置包
1:首先我们建立一个SpringBoot的quickstart,然后在POM文件中依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>1.3.4.RELEASE</version>
</dependency>
2:我们以如下图路径建立一个spring.factories的properties文件。
建立好后。我们来建立一个自动配置类。为了节省空间,笔者这里就不带引入的包了。
通过引入了
@EnableConfigurationProperties(HelloServiceProperties.class)声明了配置,就可以通过@Autowired将HelloServiceProperties的实例注入进来。
//这个注解代表这个类是个配置文件
@Configuration
//这个注解代表会去自动加载HelloServiceProperties中的所有属性
@EnableConfigurationProperties(HelloServiceProperties.class)
//这个注解代表会去import com.starrk.service.HelloService;这个路径上寻找是否有类,如果有这个类,才进行加载bean
@ConditionalOnClass(HelloService.class)
//此注解会自动去application.properties中寻找prefix为hello,name/value(这两个属性是互斥的,name是value的别名)为starrk的
//当他的值为true时,加载当前类中的所有bean,当找不到时,设置为false,即不加载。
@ConditionalOnProperty(prefix = "hello",name = "starrk",havingValue = "true",matchIfMissing = false)
public class HelloServiceAutoConfigure {
@Autowired
private HelloServiceProperties helloServiceProperties;
@Bean
@ConditionalOnMissingBean(HelloService.class)//代表当没有实例时,创建一个实例。
public HelloService helloService(){
HelloService helloService = new HelloService();
helloService.setMsg(helloServiceProperties.getMsg());
return helloService;
}
}
3:创建一个自动加载属性的类来绑定你在application.properties中配置的属性。
而HelloServiceProperties类上,如下图所示进行了配置文件绑定
@Data
@ConfigurationProperties(prefix = "hello")
public class HelloServiceProperties {
private static final String MSG = "may the force be with you";
private String msg =MSG;
}
这里的@Data是使用了Lombok插件,自动get/set,如果不使用可以手写,都是一样的。如果想使用可参考笔者文章
@ConfigurationProperties是将HelloServiceProperties与你在Application.properties中的属性进行了绑定,即如下图
4:然后我们创建一个服务类HelloService
@Data
public class HelloService {
private String msg;
public String hello(){
return "hello, "+msg;
}
}
4:装载我们的自动配置类在spring.factories中
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.starrk.autoconfig.HelloServiceAutoConfigure
至此。自动配置包我们就建立完成。下面,我们来验证一下是否成功
创建一个SpringBoot项目,然后依赖我们刚建立的包
<dependency>
<groupId>com.starrk</groupId>
<artifactId>autowired</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
建立启动类
@RestController
@SpringBootApplication
public class Application {
@Autowired
private HelloService helloService;
@RequestMapping("/")
public String hello(){
return helloService.getMsg();
}
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
配置application.properties/yml设置启动端口(可省略,随意)
设置端口为9000
启动当前的SpringBoot项目
得到结果
我们将自动配置包中的application.properties中的文件里的hello.msg注释掉。
预期得到结果为may the force be with you
至此,自动配置的手写及验证完成。而这就是Spring自动配置的过程。