小伙伴们是否想起曾经被 SSM 整合支配的恐惧? 相信很多小伙伴都是有过这样的经历的, 一大堆配置问题, 各种排除扫描, 导入一个新的依赖又得添加新的配置. 自从有了 Spring Boot 之后, 咱们就起飞了! 各种零配置开箱即用, 而我们之所以开发起来能够这么爽, 自动配置的功劳少不了, 今天我们就一起来讨论一下 Spring Boot 自动配置原理, 看完心里有个大概, 不至于被面试官问的面红耳赤.
1. SpringBoot 源码常用注解
这部分主要讲一下 SpringBoot 源码中经常使用到的注解, 以扫清后面阅读源码时候的障碍.
组合注解
当可能大量同时使用到几个注解到同一个类上, 就可以考虑将这几个注解到别的注解上. 被注解的注解我们就称之为组合注解.
元注解: 可以注解到别的注解上的注解.
组合注解: 被注解的注解我们就称之为组合注解.
@Value
@Value 就相当于传统 xml 配置文件中的 value 字段.
假设存在代码:
- @Component public class Person {
- @Value("i am name") private String name;
- }
上面代码等价于的配置文件:
<bean class="Person"> <property name ="name" value="i am name"></property></bean>
我们知道配置文件中的 value 的取值可以是:
字面量
通过 ${key} 方式从环境变量中获取值
通过 ${key} 方式全局配置文件中获取值
{SpEL}
所以, 我们就可以通过 @Value(${key}) 的方式获取全局配置文件中的指定配置项.
@ConfigurationProperties
如果我们需要取 N 个配置项, 通过 @Value 的方式去配置项需要一个一个去取, 这就显得有点 low 了. 我们可以使用 @ConfigurationProperties. 标有 @ConfigurationProperties 的类的所有属性和配置文件中相关的配置项进行绑定.(默认从全局配置文件中获取配置值), 绑定之后我们就可以通过这个类去访问全局配置文件中的属性值了.
@Import
@Import 注解支持导入普通 java 类, 并将其声明成一个 bean. 主要用于将多个分散的 java config 配置类融合成一个更大的 config 类.
@Import 注解在 4.2 之前只支持导入配置类.
在 4.2 之后 @Import 注解支持导入普通的 java 类, 并将其声明成一个 bean.
@Import 三种使用方式
直接导入普通的 Java 类.
配合自定义的 ImportSelector 使用.
配合 ImportBeanDefinitionRegistrar 使用.
@Conditional
@Conditional 注释可以实现只有在特定条件满足时才启用一些配置.
除了自定义 Condition,Spring 还为我们扩展了一些常用的 Condition.
Java 方面的架构资料, 我这里刚好有一份, 怎么领取→→→关注 + 转发 然后私信 "架构资料" 即可领取
2. SpringBoot 自动配置原理
要了解 SpringBoot 自动化配置原理就要首先来看一下 SpringbootDemoApplication.java.
- @SpringBootApplication
- public class SpringbootDemoApplication {
- public static void main(String[] args) {
- SpringApplication.run(SpringbootDemoApplication.class, args);
- }
- }
我们可以看到这个类中最耀眼的就属 @SpringBootApplication 注解了, 我们点进去看一下 @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 { }
@Target,@Retention,@Documented,@Inherited 四个注解属于元注解, 与自动配置无关, 我们不再讲解.
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
是 SpringBootApplication 的核心注解, SpringBoot 的启动类如果使用这三个注解也可以正常启动, SpringBoot 帮我们做了简化.
@SpringBootConfiguration 注解:
我们先来看看 @SpringBootConfiguration 注解的源码.
- @Target(ElementType.TYPE)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @Configuration
- public @interface SpringBootConfiguration {
- }
@SpringBootConfiguration 与 @Configuration 并没有任何区别,@Configuration 可以标注当前类是一个配置类, 并会将当前类内声明的一个或多个以 @Bean 注解标记的方法的实例纳入到 Spring IoC 容器中.
@EnableAutoConfiguration 注解:
- The second class-level annotation is @EnableAutoConfiguration. This annotation tells Spring Boot to "guess" how you <br>will want to configure Spring, based on the jar dependencies that you have added. Since spring-boot-starter-web added Tomcat and Spring MVC, <br>the auto-configuration will assume that you are developing a Web application and setup Spring accordingly.<br><br>
- Starters and Auto-Configuration
- Auto-configuration is designed to work well with "Starters", but the two concepts are not directly tied. <br>You are free to pick-and-choose jar dependencies outside of the starters and Spring Boot will still do <br>its best to auto-configure your application.
这个注释告诉 SpringBoot"猜" 你将如何想配置 Spring, 基于你已经添加 jar 依赖项. 如果 spring-boot-starter-Web 已经添加 Tomcat 和 Spring MVC, 这个注释自动将假设您正在开发一个 Web 应用程序并添加相应的 spring 设置.
自动配置被设计用来和 "Starters" 一起更好的工作, 但这两个概念并不直接相关. 您可以自由挑选 starter 依赖项以外的 jar 包, springboot 仍将尽力自动配置您的应用程序.
spring 通常建议我们将 main 方法所在的类放到一个 root 包下,@EnableAutoConfiguration(开启自动配置) 注解通常都放到 main 所在类的上面, 下面是一个典型的结构布局:
- com
- +- example
- +- myproject
- +- Application.java
- |
- +- domain
- | +- Customer.java
- | +- CustomerRepository.java
- |
- +- service
- | +- CustomerService.java
- |
- +- Web
- +- CustomerController.java
这样 @EnableAutoConfiguration 可以从逐层的往下搜索各个加注解的类, 例如, 你正在编写一个 JPA 程序 (如果你的 pom 里进行了配置的话),spring 会自动去搜索加了 @Entity 注解的类, 并进行调用
@ComponentScan 注解:
@ComponentScan 注解是我们非常熟悉的一个注解,@ComponentScan 的功能就是自动扫描并加载符合条件的组件或 Bean 定义, 最终将这些 bean 定义加载到当前使用的容器中.
通过以上三个注解, SpringBoot 便完成了它的自动化配置, 你看明白了吗?
至此, 我们可以总结一下 Spring Boot 的自动化配置的实现:
来源: http://www.jianshu.com/p/c894fc210a89