Spring配置方式
第一阶段:xml配置
在spring 1.x时代,使用spring开发满眼都是xml配置的bean,随着项目的扩大,
我们需要把xml配置文件分放到不同的配置文件中,那时候需要频繁地在开发的类和配置文件间切换。
第二阶段:注解配置
在spring 2.x时代,随着JDK1.5带来的注解支持,spring提供了声明bean的注解,
大大减少了配置量。这时spring圈子存在一种争论:注解配置和xml配置究竟哪个更好?我们最终的选择是应用
的基本配置用xml,业务配置用户注解。
第三阶段:Java配置(java config)
从spring 3.x到现在,spring提供了Java配置的能力,使用Java配置更好的理解
配置的bean。spring 4.x和spring boot都推荐使用Java配置。
Spring IOC有一个非常核心的概念——Bean。由Spring容器来负责对Bean的实例化,装配和管理。XML是用来描述Bean最为流行的配置方式。但随着Spring的日益发展,越来越多的人对Spring提出了批评。“Spring项目大量的烂用XML”就是最为严励的一个批评。由于Spring会把几乎所有的业务类都以Bean的形式配置在XML文件中,造成了大量的XML文件。使用XML来配置Bean失去了编译时的类型安全检查。大量的XML配置使得整个项目变得更加复杂。
随着JAVA EE 5.0的发布,其中引入了一个非常重要的特性——Annotations(注释)。注释是源代码的标签,这些标签可以在源代码层进行处理或通过编译器把它熔入到class文件中。在JAVA EE5以后的版本中,注释成为了一个主要的配置选项。Spring使用注释来描述Bean的配置与采用XML相比,因类注释是在一个类源代码中,可以获得类型安全检查的好处。可以良好的支持重构。
SpringBoot 配置方式
当我们构建完Spring Boot项目后,会在resources目录下给我们一个默认的全局配置文件 application.properties,这是一个空文件,因为Spring Boot在底层已经把配置都给我们自动配置好了,当在配置文件进行配置时,会修改SpringBoot自动配置的默认值。
配置文件名是固定的
application.properties
但我们可以修改为
application.yml
这两个文件本质是一样的,区别只是其中的语法略微不同。
自定义配置
1 |
@ConfigurationProperties 注解向Spring Boot声明该类中的所有属性和配置文件中相关的配置进行绑定。
- prefix = “person”:声明配置前戳,将该前戳下的所有属性进行映射。
@Component 或者@Configuration:将该组件加入Spring Boot容器,只有这个组件是容器中的组件,配置才生效。
配置文件加载位置
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
- –file:./config/
- –file:./
- –classpath:/config/
- –classpath:/
优先级由高到底,高优先级的配置会覆盖低优先级的配置;SpringBoot会从这四个位置全部加载主配置文件。、
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
自动装配
自动装配主要由
@EnableAutoConfiguration实现,添加了@EnableAutoConfiguration注解,会导入AutoConfigurationImportSelector类,里面的selectImports方法通过SpringFactoriesLoader.loadFactoryNames()扫描所有含有META-INF/spring.factories的jar包,将对应key为@EnableAutoConfiguration注解全名对应的value类全部装配到IOC容器中。
相比较于传统的 Spring 应用,搭建一个 SpringBoot 应用,我们只需要引入一个注解 @SpringBootApplication,就可以成功运行。
核心注解 SpringBootApplication 。
1 |
|
大概可以把 @SpringBootApplication看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。根据 SpringBoot 官网,这三个注解的作用分别是:
@EnableAutoConfiguration:启用 SpringBoot 的自动配置机制@Configuration:允许在上下文中注册额外的 bean 或导入其他配置类@ComponentScan: 扫描被@Component(@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean。
@SpringBootConfiguration 注解
这个注解我们点进去就可以发现,它实际上就是一个 @Configuration 注解,这个注解大家应该很熟悉了,加上这个注解就是为了让当前类作为一个配置类交由 Spring 的 IOC 容器进行管理,因为前面我们说了,SpringBoot 本质上还是 Spring,所以原属于 Spring 的注解 @Configuration 在 SpringBoot 中也可以直接应用。
@ComponentScan 注解
这个注解也很熟悉,用于定义 Spring 的扫描路径,等价于在 xml 文件中配置 context:component-scan,假如不配置扫描路径,那么 Spring 就会默认扫描当前类所在的包及其子包中的所有标注了 @Component,@Service,@Controller 等注解的类。
@EnableAutoConfiguration:实现自动装配的核心注解
EnableAutoConfiguration 只是一个简单地注解,自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector类。
1 |
|
我们现在重点分析下AutoConfigurationImportSelector 类到底做了什么?
AutoConfigurationImportSelector:加载自动装配类
AutoConfigurationImportSelector类的继承体系如下:
1 | public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { |
可以看出,AutoConfigurationImportSelector 类实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。
1 | private static final String[] NO_IMPORTS = new String[0]; |
这里我们需要重点关注一下getAutoConfigurationEntry()方法,这个方法主要负责加载自动配置类的。
原理流程汇总
从上面查看的源码,可以知道Spring Boot自动配置主要是@EnableAutoConfiguration实现的,@EnableAutoConfiguration注解导入AutoConfigurationImportSelector类,通过selectImports方法调用SpringFactoriesLoader.loadFactoryNames()扫描所有含有META-INF/spring.factories文件的jar包,将spring.factories文件中@EnableAutoConfiguration对应的类注入到IOC容器中。
这些属性自动配置到IOC之后就无需自己手动配置bean了,Spring Boot中的约定大于配置理念,约定是将需要的配置以约定的方式添加到IOC容器中。
自动配置生效条件
那是不是spring.factories文件对应的配置都会加载到IOC容器中?比如下面的Kafka自动配置类:
1 | @Configuration |
其中有几个注解:
1 | @ConditionalOnClass |
@ConditionalOnClass表示在类路径中存在类才会配置该配置类。只有引入相关依赖才会自动配置该配置类。@ConditionalOnMissingBean表示只有不存在对应的类的bean才会自动配置该类。
所以spring.factories里面并不是所有的bean都会装配到IOC容器中,只会按需配置对应的bean。
总结
Spring Boot 自动装配原理
@EnableAutoConfiguration注解导入AutoConfigurationImportSelector类,开启自动配置(@SpringBootApplication注解默认已包含)。自动加载类路径下
META-INF/spring.factories文件,读取以EnableAutoConfiguration的全限定类名对应的值,作为候选配置类。这里默认给出了很多组件的自动配置类。- 执行
selectImports方法调用SpringFactoriesLoader.loadFactoryNames()扫描所有jar下面的对应的META-INF/spring.factories文件. - 限定为
@EnableAutoConfiguration对应的value,将这些装配条件的装配到IOC容器中。
- 执行
自动配置类可能会再导入一些依赖(比如
@Import),或者给出一些配置条件,并且会通过@Bean注解把该组件所包含的组件注入到spring容器中以供使用。自动配置类还可能会绑定xxxProperties配置文件类,该类又会和应用程序中的
application.properties中的指定前缀绑定。第3步注入组件的时候,组件可能还会获取配置文件类中的内容,所以用户可以在application.properties修改指定配置,来制定自己的个性化服务。
自动装配简单来说就是自动将第三方的组件的bean装载到IOC容器内,不需要再去写bean相关的配置,符合约定大于配置理念。
Spring Boot基于约定大于配置的理念,配置如果没有额外的配置的话,就给按照默认的配置使用约定的默认值,按照约定配置到IOC容器中,无需开发人员手动添加配置,加快开发效率。
starter
starter会把所有用到的依赖包都包含进来,避免开发者自己去引入依赖所带来的麻烦。
虽然不同的starter实现起来各有差异,但是他们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfiguration。

Starter是一组可以让你很方便的在应用增加的依赖关系描述符的集合。或者可以这样理解,平时我们开发的时候很多情况下都会有一个模块依赖另一个模块,这个时候我们一般都是采用maven的模块依赖,进行模块的依赖,但是这种情况下我们完全可以采用Starter的方式,将需要被依赖的模块用Starter的方式去开发,最后直接引入一个Starter也可以达到这样的效果。
命名规则
由于SpringBoot官方本身就提供了很多Starter,为了区别那些是官方的,哪些是第三方的,所以SpringBoot官方提出:
- 官方定义的starter组件命名一般为
spring-boot-starter-xxx - 自定义starter组件命名一般为
xxx-spring-boot-starter
总结自定义starter的主要流程和注意事项:
- 规范是定义一个
starter模块和autoconfigure模块,starter模块依赖autoconfigure模块,并提供启动所需的依赖。starter模块不提供服务。 - 在命名上,一般是
前缀-spring-boot-starter和前缀-spring-boot-autoconfigure,比如mybatis-spring-boot-starter。 - 可以编写xxxProperties配置文件,按照自己的需求,提供可自定义的配置选项。
autoconfigure模块中编写自己的服务类,可以导入配置文件并使用其中的配置。- 自动配置类要标注
@Configuration注解,用@EnableConfigurationProperties绑定配置文件,可按照自己的需求,给出自动配置的条件、时机、顺序等。用@Bean把自己所要暴露的服务类提供出来,让其注入到Spring容器中。 - 新建
META-INF/spring.factories文件,把自己的配置类全类名绑定到Spring Boot自动配置类的全类名上。如下所示:
1 | # Auto Configure |
- 打包发布两个模块。