作者:你在我家门口原文:https://juejin.im/post/5ce5effb6fb9a07f0b039a1
前言
小伙伴们是否想起曾经被 SSM 整合支配的恐惧?相信很多小伙伴都是有过这样的经历的,一大堆配置问题,各种排除扫描,导入一个新的依赖又得添加新的配置。自从有了 SpringBoot 之后,咋们就起飞了!各种零配置开箱即用,而我们之所以开发起来能够这么爽,自动配置的功劳少不了,今天我们就一起来讨论一下 SpringBoot 自动配置原理。
本文主要分为三大部分:
- SpringBoot 源码常用注解拾遗
- SpringBoot 启动过程
- SpringBoot 自动配置原理
1. SpringBoot 源码常用注解拾遗
这部分主要讲一下 SpringBoot 源码中经常使用到的注解,以扫清后面阅读源码时候的障碍。
组合注解
当可能大量同时使用到几个注解到同一个类上,就可以考虑将这几个注解到别的注解上。被注解的注解我们就称之为组合注解。
- 元注解:可以注解到别的注解上的注解。
- 组合注解:被注解的注解我们就称之为组合注解。
@Value 【Spring 提供】
@Value 就相当于传统 xml 配置文件中的 value 字段。
假设存在代码:
@Component public class Person { @Value("i am name") private String name; }
上面代码等价于的配置文件:
我们知道配置文件中的 value 的取值可以是:
- 字面量
- 通过 ${key} 方式从环境变量中获取值
- 通过 ${key} 方式全局配置文件中获取值
- #{SpEL}
所以,我们就可以通过 @Value(${key}) 的方式获取全局配置文件中的指定配置项。
@ConfigurationProperties 【SpringBoot 提供】
如果我们需要取 N 个配置项,通过 @Value 的方式去配置项需要一个一个去取,这就显得有点 low 了。我们可以使用 @ConfigurationProperties 。
标有 @ConfigurationProperties 的类的所有属性和配置文件中相关的配置项进行绑定。(默认从全局配置文件中获取配置值),绑定之后我们就可以通过这个类去访问全局配置文件中的属性值了。
下面看一个实例:
- 在主配置文件中添加如下配置
person.name=kundy person.age=13 person.sex=male
- 创建配置类,由于篇幅问题这里省略了 setter、getter 方法,但是实际开发中这个是必须的,否则无法成功注入。另外,@Component 这个注解也还是需要添加的。
@Component @ConfigurationProperties(prefix = "person") public class Person { private String name; private Integer age; private String sex; }
这里 @ConfigurationProperties 有一个 prefix 参数,主要是用来指定该配置项在配置文件中的前缀。
- 测试,在 SpringBoot 环境中,编写个测试方法,注入 Person 类,即可通过 Person 对象取到配置文件的值。
@Import 【Spring 提供】
@Import 注解支持导入普通 java 类,并将其声明成一个bean。主要用于将多个分散的 java config 配置类融合成一个更大的 config 类。
- @Import 注解在 4.2 之前只支持导入配置类。
- 在4.2之后 @Import 注解支持导入普通的 java 类,并将其声明成一个 bean。
**@Import 三种使用方式 **
- 直接导入普通的 Java 类。
- 配合自定义的 ImportSelector 使用。
- 配合 ImportBeanDefinitionRegistrar 使用。
1. 直接导入普通的 Java 类
- 创建一个普通的 Java 类。
public class Circle { public void sayHi() { System.out.println("Circle sayHi()"); } }
- 创建一个配置类,里面没有显式声明任何的 Bean,然后将刚才创建的 Circle 导入。
@Import({Circle.class}) @Configuration public class MainConfig { }
- 创建测试类。
public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); Circle circle = context.getBean(Circle.class); circle.sayHi(); }
- 运行结果:
C