单体应用逐渐变得臃肿,牵一发而动全身。 大量的xml文件 集合第三方框架问题
这是一个springBoot配置类
@Configuration:配置类上标注这个注解配置类-配置文件:配置类也是容器中的组件@Component
开启自动配置功能
@AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { @AutoConfigurationPackage:自动配置包 将启动类所在包及以下所有组件扫描到容器中@Import({Registrar.class}):spring底层注解 导入组件
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { Registrar() { } //将启动类所在包及以下所有组件扫描到容器中 public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0])); } public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata)); } } @Import({AutoConfigurationImportSelector.class}):导入组件选择器将所有需求的组件以全类名的方式返回,这些组件会被添加到容易中。
//annotationMetadata 元信息 protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { if (!this.isEnabled(annotationMetadata)) { //不开启自动装配 返回空 return EMPTY_ENTRY; } else { AnnotationAttributes attributes = this.getAttributes(annotationMetadata); List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); configurations = this.removeDuplicates(configurations); Set<String> exclusions = this.getExclusions(annotationMetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.getConfigurationClassFilter().filter(configurations); this.fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions); } }会给容器中导入很多自动配置类(XXautoconfig)
有了spring自动配置的类,我们就不用自己去做了
那么具体是如何加载的呢?看下面方法
//读取项目下的配置类 一般为 spring.factories List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());Spring 在启动的时候从类路径下META-INF/spring.factories获取EnableAutoConfiguration指定的值,将自动配置类导入容器中。
IDEA-NEW-Spring initializr-web 就可以创建一个简单的SpringBoot项目了
启动类生成resources static:静态资源 templates:所有模板页面(默认不支持jsp 需要手动配置 )application.properties :springboot 应用配置文件application.properties application.yml
配置文件作用:修改SpringBoot自动配置默认值
YAML 以数据为中心,比XML、json更适合做配置文件 server: port: 7949字符串默认不加单引号或双引号
双引号:不会转义 zhang\nLi -> zhang 换行Li
单引号:会 zhang\nLi ->zhang\nLi
对象: swagger: version: enabled: true base-path: /**行内写法
swagger: {version: 0.1,enabled: tre} 集合:用- 表示数据组中的一个元素
swagger: - version: - enabled: true - base-path: /**行内写法
swagger: [version,enabled]只获取配置文件的某项值,使用@value 获取全部数据使用@ConfigurationProperties
创建beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="helloService" class="cn.zhangyu.service.HelloService"></bean> </beans>@ImportResource标注在配置类上
@ImportResource(locations = {"classpath:beans.xml"}) @SpringBootApplication public class Springboot1Application { public static void main(String[] args) { SpringApplication.run(Springboot1Application.class, args); } } @Bean @Configuration public class MyAppConfig { //将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名 //也可以指定别名 name='111' @Bean("helloService1") public HelloService helloService(){ System.out.println("配置类@Bean给容器中添加组件了..."); return new HelloService(); } }配置文件起名application-{profile}.properties/yml
application-dev.properties
application-prod.properties
默认使用application.properties
yml支持文档块模式 server: port: 8081 spring: profiles: active: prod //通过这个控制采取哪个配置 --- server: port: 8083 spring: profiles: dev --- server: port: 8084 spring: spring: prod 指定激活 指定配置,在默认配置文件中指定Spring.profile.active=devspring.profiles.active=prod//通过这个调用
命令行激活 java -jar xxx.jar **--spring.profiles.active=dev**idea 可以直接在 edit configuration 设置
虚拟机参数 vm options= -Dspring.profiles.active=dev1. 按照优先级从高到低,高优先级会覆盖低优先级内容,形成互补配置
file:./config/ (当前项目路径config目录下);file:./ (当前项目路径下);classpath:/config/ (类路径config目录下);classpath:/ (类路径config下).源码展示
public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered { private static final String DEFAULT_PROPERTIES = "defaultProperties"; private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/"; spring.config.location 项目打包后,使用命令行参数来指定配置文件位置 ,会和项目中的配置文件形成互补。 spring.config.location= 这个配置决定了会从哪些地方去加载配置文件,如果你修改了它。那么就会覆盖掉默认的配置。只会从你指定的位置去加载配置文件。spring.config.additional-location=这个配置也可以达到相同的目的,修改springboot加载配置文件的目录,但是它不会覆盖默认的,只会新增指定的路径。 //CONFIG_LOCATION_PROPERTY=spring.config.location //CONFIG_ADDITIONAL_LOCATION_PROPERTY = "spring.config.additional-location" private Set<String> getSearchLocations() { if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) { return getSearchLocations(CONFIG_LOCATION_PROPERTY); } Set<String> locations = getSearchLocations( CONFIG_ADDITIONAL_LOCATION_PROPERTY); locations.addAll( asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS)); return locations; }实际工作中可以查阅资料使用
配置文件属性参考官方文档
spring启动时加载主配置类,开启自动配置功能@EnableAutoConfiguration@EnableAutoConfiguration利用AutoConfigurationImportSelector给容器导入组件。 类路径下spring.factories里面配置的所有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.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ more.....每一个xxxAutoConfiguration都是容器中的一个组件,以此来实现自动配置
以HttpEncodingAutoConfiguration来解释自动配置原理 //配置类 @Configuration(proxyBeanMethods = false) //启用指定类的@ConfigurationProperties @EnableConfigurationProperties(ServerProperties.class) //spring底层注解@Conditional 的作用是按照一定的条件进行判断,满足条件给容器注册bean //判断当前应用是否位web应用 @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) //当前项目是否有这个类 @ConditionalOnClass(CharacterEncodingFilter.class) //是否存在某个配置 server.servlet.encoding=enabled 如果不存在 默认为存在 @ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration {根据当前不同条件判断,决定配置类是否生效
从对应的properties获取属性,使配置类生效。
一旦配置类生效,会给容器中加组件
//既spring boot默认配置文件 private final Encoding properties; public HttpEncodingAutoConfiguration(ServerProperties properties) { this.properties = properties.getServlet().getEncoding(); } //添加组件 @Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE)); return filter; }总结
spring启动会加载大量配置类我们需要的功能spring是否有默认的自动配置类。如果没有 需要在properties配置相关属性,spring从而加载相对应的配置类及其组件。作用:只有@Conditional指定的条件生效,才会向容器中添加组件
@Conditional扩展注解作用(判断是否满足当前指定条件)@ConditionalOnJava系统的java版本是否符合要求@ConditionalOnBean容器中存在指定Bean;@ConditionalOnMissingBean容器中不存在指定Bean;@ConditionalOnExpression满足SpEL表达式指定@ConditionalOnClass系统中有指定的类@ConditionalOnMissingClass系统中没有指定的类@ConditionalOnSingleCandidate容器中只有一个指定的Bean,或者这个Bean是首选Bean@ConditionalOnProperty系统中指定的属性是否有指定的值@ConditionalOnResource类路径下是否存在指定资源文件@ConditionalOnWebApplication当前是web环境@ConditionalOnNotWebApplication当前不是web环境@ConditionalOnJndiJNDI存在指定项怎么知道那些配置类是自动生效?
debug=true