1. 全局配置文件
SpringBoot项目使用一个全局配置文件application.properties或者是application.yml来进行全局配置。
配置位置:一般来讲,配置文件一般放在resource目录下或者类路径下的/config下。通常我们都是放在resource下。
我们来看下@SpringBootApplication注解的源码
spring:
profiles:
# 使用那个配置
active: prod
datasource:
name: dataSource
username: XXX
password: XXX
# 使用druid数据源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
# filters: stat
# maxActive: 20
# initialSize: 1
# maxWait: 60000
# minIdle: 1
# timeBetweenEvictionRunsMillis: 60000
# minEvictableIdleTimeMillis: 300000
# validationQuery: select 'x'
# testWhileIdle: true
# testOnBorrow: false
# testOnReturn: false
# poolPreparedStatements: true
# maxOpenPreparedStatements: 20
# removeAbandoned: false
logging:
config: classpath:logbak.xml
#server:
# ssl:
# key-store: classpath:vc.dahancloud.com.jks
# key-store-password: 4zc8zi119d2
---
# 开发环境配置
spring:
profiles: dev
datasource:
url: jdbc:mysql://localhost:3306/iot?useUnicode=true&characterEncoding=UTF-8
server:
port: 8080
---
# 测试环境配置
spring:
profiles: prod
datasource:
url: jdbc:mysql://x.x.x.x:3306/iot?useUnicode=true&characterEncoding=UTF-8
server:
port: 9097
alarmservice:
alarm: http://localhost:8093
说明:springboot的全局配置文件除了以上这些还有很多,可以参考一下API文档。
2. starter pom
SpringBoot为我们提供了简化企业开发绝大多数场景的starter pom,只要使用了应用场景所需要的starter pom,相关的技术配置就会消除,就可以得到SpringBoot为我们提供的自动配置Bean。
官方文档上提供的start pom有以下:
名称 | 描述 |
---|---|
spring-boot-start | SpringBoot核心start,包含自动配置、日志、yml配置文件的支持 |
spring-boot-start-actuator | 准生产特性,用来监控和管理应用 |
spring-boot-start-remote-shell | 提供基于SSH协议的监控和管理 |
spring-boot-starter-amqp | 使用spring-rabbit来支持AMQP |
spring-boot-start-aop | 使用spring-aop和AspectJ支持面向切面编程 |
spring-boot-starter-batch | 对Spring Batch支持 |
spring-boot-starter-cloud-connectors | 对云平台(Cloud Foundy、Heroku)提供的服务提供简化的连接方式 |
spring-boot-starter-data-elasticsearch | 通过spring-data-elasticsearch对Elasticsearch支持 |
spring-boot-starter-data-gemfire | 通过spring-data-gemfire对分布式存储GemFile的支持 |
spring-boot-starter-data-jpa | 对JPA的支持,包含spring-data-jpa、spring-orm和Hibernate |
spring-boot-starter-jdbc | 对JDBC数据库的支持 |
spring-boot-starter-mail | 对javax.mail的支持 |
spring-boot-starter-redis | 对键值对内存数据库Redis的支持,包含spring-redis |
spring-boot-starter-security | 对spring-security的支持 |
spring-boot-starter-social-facebook | 通过spring-social-facebook对Facebook的支持 |
spring-boot-starter-web | 对web项目开发的支持,包含Tomcat和spring-webmvc |
spring-boot-starter-Tomcat | SpringBoot默认的Servlet容器Tomcat |
spring-boot-starter-logging | Sping Boot 默认的日志框架Logback |
spring-boot-starter-log4j | 支持使用Log4J日志框架 |
spring-boot-starter-websocket | 对WebSocket开发的支持 |
spring-boot-starter-ws | 对Spring Web Services的支持 |
以上是列举一些starter pom ,还有一些并没有列举出来。如果需要可以自己去查阅文档。并且一些第三方技术都有自己推出的starter pom
3. 自动配置分析
我们可以通过maven的命令dependency:sources来下载该maven项目中的所有依赖包的源码。
我们在使用SpringBoot的时候会先生成一个SpringApplicaiton类,于是我们来分析一下这个类在生成中是如何进行自动配置的:/font>
//SpringApplicaiotn类的初始化方法
@SuppressWarnings({"unchecked","rawtypes"})
private void initialize (Object[] sources){
if(sources!=null && sources.length>0){
this.sources.addAll(Arrays.asList(source));
}
this.webEnvironment = deduceWebEnvironment();
//注意这一步,这一步是进行自动配置
setInitializers((Collection)getSpringFactoriesInstances(
ApplictionContextInitializer.class));
setListeners((Collection)getSpringFactoriesInstances(
ApplicaitonListener.class));
this.mainApplicationClass = deduMainApplicationClass();
}
接着我们来看一下getSpringFactoriesInstance方法的源码
private <T> Collection<? extends T>getSpringFactoriesInstance(Class<T> type){
return getSpringFactoriesInstance(type, new Class<?>[]{});
}
//我们来看下getSpringFactoriesInstance这个方法源码
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] paramterTypes, Object... args){
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//使用names确保唯一性,防止重复
Set<String> names = new LinkedHashSet<String>(
//类加载器
SpringFactoriesLoader.loadFactoryNames(type,classLoader));
List<T> instances = createrSpringFactoriesInstances(type,parameterTypes,
classLoader,args,names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
我们来看下通过loadFactoryNames方法加载的情况
//配置的路径
public static final String FACTORIES_RESOURCE_LOCATION =
"META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryClass,
ClassLoader classLoder){
String factoryName = factoryClass.getName();
try{
Enumeration<URL> urls =(ClassLoader!=null ?
ClassLoader.getResource(FACTORIES_RESOURCE_LOCATION)) :
ClassLoader.getSystemResource(FACTORIES_RESOURCE_LOCATION);
List<String> result = new ArrayList<String>();
while(urls.hasMoreElements()){
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(
new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Array.asList(
StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}catch(IOException ex){
throw new IllegalArgumentException("Unable to load ["
+ factoryClass.getName)+"] factories from location ["
+ FACTORIES_RESOURCE_LOCATION + "]",ex);
}
}
SpringBoo在进行SpringApplication对象实例化时会加载META-INF/spring.factories
将其转变成对象,将该配置文件中的配置载入到Spring容器中。而这个配置文件里面配置了很多内容。
4. 条件注解
我们在翻阅自动配置的过程中,可以回遇见很多条件注解,这边把常见的条件注解列举一下:
注解 | 解释 |
---|---|
@ConditionalOnClass({xxx.class}) | 当存在xxx类的情况下,才会实例化该类 |
@ConditionalOnBean | 当容器里有指定的Bean的情况下 |
@ConditionalOnExpression | 基于SpEL表达式作为判断条件 |
@ConditionalOnJava | 基于JVM版本作为判断条件 |
@ConditionalOnJndi | 在JNDI存在的条件下查找指定的位置 |
@ConditionalOnMissingBean | 当容器里没有指定Bean的情况下 |
@ConditionalOnMissingClass | 当容器里没有指定类的条件下 |
@ConditionalOnNotWebApplication | 当前项目不是web项目的情况下 |
@ConditionalOnProperty | 指定属性是否有指定的值 |
@ConditionalOnResource | 类路径是否有指定的值 |
@ConditionalOnSingleCandidate | 指定Bean在容器中只有一个, |
或者虽然有多个但是指定首选的Bean | |
@ConditionalOnWebApplicaiton | 当前项目时Web项目的条件下 |