您的位置:首页 > 编程语言 > Java开发

spring-boot自动配置

2017-06-13 00:00 411 查看
摘要: spring-boot的自动配置大大简化了开发中繁琐的配置,今天下午研究了一下实现这神奇功能的原理。

先看下@SpringBootApplication这个注解,这是一个组合注解,部分源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//省略若干代码...
}

可以看到@EnableAutoConfiguration这个注解,这个就是自动配置的核心所在,接下来看下这个注解的源码:

@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
//省略若干行代码...
}

可以发现此处导入了EnableAutoConfigurationImportSelector.class这个类,继续观察EnableAutoConfigurationImportSelector这个类的源码

public class EnableAutoConfigurationImportSelector
extends AutoConfigurationImportSelector {
//省略若干行代码
}

发现继承于AutoConfigurationImportSelector这个类,发现有如下代码

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}

这里扫描了具有META-INF/spring.factories文件的jar包。点开具有*autoconfigure的包,打开META-INF/spring.factories文件,发现有类似
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration
,打开任意一个AutoConfiguration,可以发现有如下注解:

@Configuration
@EnableConfigurationProperties(UeditorProperties.class)
@ConditionalOnClass(ActionEnter.class)
@ConditionalOnProperty(prefix="ueditor",value="enabled",matchIfMissing=true)


@Configuration

EnableConfigurationProperties 属性注入类

ConditionalOnClass 条件注解,当容器有指定的Bean的条件下。

ConditionalOnProperty 条件注解,指定属性是否有指定的值,这个注解测试了下,没有达到预期效果,不知道怎么回事。

这里便是spring-boot自动配置的秘密所在了,接下来自己建一个项目,让其也拥有自动配置的功能:当类存在时,自动配置这个类的Bean,并可将Bean的属性在appliction.properties中配置。

pom中引入相关组件

<dependencies>
<!--自动配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring-boot}</version>
</dependency>

<!--属性的自动注入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
<version>${spring-boot}</version>
</dependency>
</dependencies>


属性配置,类型安全属性获取。

@ConfigurationProperties(prefix = "hello")
public class HelloServiceProperties {
private static final String MSG = "world";

private String msg = MSG;

public static String getMSG() {
return MSG;
}

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}
}


根据HelloService这个类是否存在,来创建这个类的Bean

public class HelloService {
private String msg;

public String sayHello(){
return "hello"+msg;
}

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}
}


自动配置类

@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class)
@ConditionalOnClass(HelloService.class)
public class HelloServiceAutoConfigure {

@Autowired
private HelloServiceProperties helloServiceProperties;

@Bean
@ConditionalOnMissingBean(HelloService.class)
public HelloService helloService() {
HelloService helloService = new HelloService();
helloService.setMsg(helloServiceProperties.getMsg());
return helloService;
}
}


注册自动配置类,在src/main/resources目录下,新建META-INF目录并在其中新建spring.factories文件,输入如下代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.xiake.springboot.start.hello.HelloServiceAutoConfigure


这里,一个拥有自动配置的项目完成。在其他项目中引用maven坐标,并在application.properties中自定义hello.msg="xxx".使用代码如下:

@Autowired
HelloService helloService;

@ResponseBody
@RequestMapping("/sayHello")
public ResponseData sayHello(HttpServletRequest request){
return ResponseData.success(helloService.sayHello()); //输出hello.msg中的内容:xxx
}

项目源码地址
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Spring Boot