亲手实现一个springboot默认配置&起步加载
原创
©著作权归作者所有:来自51CTO博客作者super彦的原创作品,请联系作者获取转载授权,否则将追究法律责任
实现
一、默认配置
1、创建springboot项目引入spring-boot-dependencies依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
spring-boot-autoconfigure 是springboot自动配置依赖,springboot提供的默认配置都在这个依赖中
开启自动配置注解:
- @SpringBootApplication (内部包含了@EnableAutoConfiguration)
2、创建配置类
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
//包含GreetingApplicationRunner这个类时才会生效
@ConditionalOnClass(GreetingApplicationRunner.class)
public class GreetingAutoConfiguration {
@Bean
//当spring容器中没有GreetingApplicationRunner类时加载
@ConditionalOnMissingBean(GreetingApplicationRunner.class)
// greeting.enabled 值等于 true时配置加载;matchIfMissing = true greeting.enabled值为空时也加载
@ConditionalOnProperty(name = "greeting.enabled", havingValue = "true", matchIfMissing = true)
public GreetingApplicationRunner greetingApplicationRunner() {
return new GreetingApplicationRunner();
}
}
3、在resources目录下创建META-INF/spring.factories 写入:
# 自动配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
geektime.spring.hello.greeting.GreetingAutoConfiguration
@EnableAutoConfifiguration
- 加载AutoConfigurationImportSelector类
- META-INF/spring.factories
- org.springframework.boot.autoconfigure.EnableAutoConfiguration
spring.factories 文件
注意:
/spring.factories: 定位自动配置
@Configuration注解和/spring.factories文件可以只写一个,建议两个都写
二、实现起步依赖(启动加载)
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
@Slf4j
public class GreetingApplicationRunner implements ApplicationRunner {
public GreetingApplicationRunner() {
log.info("Initializing GreetingApplicationRunner.");
}
public void run(ApplicationArguments args) throws Exception {
log.info("Hello everyone! We all like Spring! ");
}
}
实现ApplicationRunner 接口可以实现起步加载
默认配置核心是对Conditiona相关注解的运用
起步加载核心:ApplicationRunner
附
我们来看一下spring-boot-autoconfigure 中的META-INF/spring.factories文件写了哪些内容
# Initializers 初始化
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners 监听器
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
#以上是于spring-cloud-context相关的jar
# 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.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# 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
#...
#springboot自动配置都在这里配置,把你的配置类权限限定名写在这里
#以上是于spring-boot-autoconfigure相关的jar
# Failure analyzers 故障分析
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer
# Template availability providers 模板
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
@Conditional 用法
使用@Conditional控制@Configuration 是否生效
作用:总而言之,只有@Conditional指定的条件成立,才给容器添加组件
@Conditional派生注解:@Conditional派生了很多注解,下面给个表格列举一下派生注解的用法
@Conditional派生注解
| 作用(都是判断是否符合指定的条件)
|
@ConditionalOnJava
| 系统的java版本是否符合要求
|
@ConditionalOnBean
| spring容器有指定的Bean类
|
@ConditionalOnMissingBean
| spring容器没有指定的bean类
|
@ConditionalOnExpression
| 符合指定的SpEL表达式
|
@ConditionalOnClass
| 有指定的类(好像是你的工程中存在这个类)
|
@ConditionalOnMissingClass
| 没有指定的类(好像是你的工程中不存在这个类)
|
@ConditionalOnSingleCandidate
| 容器只有一个指定的bean,或者这个bean是首选bean
|
@ConditionalOnProperty
| 指定的property属性有指定的值
|
@ConditionalOnResource
| 路径下存在指定的资源
|
@ConditionalOnWebApplication
| 系统环境是web环境
|
@ConditionalOnNotWebApplication
| 系统环境不是web环境
|
@ConditionalOnjndi
| JNDI存在指定的项
|
@ConditionalOnClass
某个class位于类路径上,才会实例化一个Bean。即判断当前classpath下是否存在指定类,若是则将当前的配置装载入spring容器
ConditionalOnProperty
application.properties 属性值符合指定条件时生效
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
//获取对应property名称的值,与name不可同时使用
String[] value() default {};
//property名称的前缀,可有可无
String prefix() default "";
//property完整名称或部分名称(可与prefix组合使用,组成完整的property名称),与value不可同时使用
String[] name() default {};
//可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置
String havingValue() default "";
//缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错
boolean matchIfMissing() default false;
//是否可以松散匹配,指命名方式支持驼峰横线方式兼容
boolean relaxedNames() default true;
}
}
其中name用来从application.properties中读取某个属性值。如果该值为空,则返回false(havingValue = "true"时返回true,默认havingValue = “false”);
如果值不为空,则将该值与havingValue指定的值进行比较,如果一样则返回true;否则返回false。
如果返回值为false,则该configuration不生效;为true则生效。
代码:https://github.com/liuyanqing1023/geektime-spring-family/tree/master/Chapter%209