赞
踩
Spring Boot的自动配置是指Spring Boot根据应用程序的依赖和配置信息,自动为应用程序进行配置,减少了开发人员手动配置的工作量。
Spring Boot的自动配置基于条件注解和Spring Boot Starter的机制。条件注解是通过判断一定的条件是否满足来决定是否应用某个配置。Spring Boot Starter是一种特殊的依赖,它包含了一组相关的依赖和配置,可以通过引入该Starter来自动配置相关的功能。
Spring Boot的自动配置可以通过以下几种方式实现:
1. 使用@EnableAutoConfiguration注解
2. 使用@ConfigurationProperties注解
在Spring Boot的主配置类上添加@EnableAutoConfiguration注解,Spring Boot会根据类路径上的依赖自动进行配置。@Enable底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。而@Import提供4中用法:
@SpringBootApplication注解内部
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan(
- excludeFilters = {@Filter(
- type = FilterType.CUSTOM,
- classes = {TypeExcludeFilter.class}
- ), @Filter(
- type = FilterType.CUSTOM,
- classes = {AutoConfigurationExcludeFilter.class}
- )}
- )
- public @interface SpringBootApplication {
- // ......
- }
@ComponentScan
这个注解在Spring中很重要 ,它对应XML配置中的元素。
作用:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中
@SpringBootConfiguration
作用:SpringBoot的配置类 ,标注在某个类上 , 表示这是一个SpringBoot的配置类;
- //@SpringBootConfiguration注解内部
- //这里的 @Configuration,说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件;
- @Configuration
- public @interface SpringBootConfiguration {}
- //里面的 @Component 这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用
- @Component
- public @interface Configuration {}
@AutoConfigurationPackage :自动配置包
- //AutoConfigurationPackage的子注解
- //Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器
- @Import({Registrar.class})
- public @interface AutoConfigurationPackage {
- }
@EnableAutoConfiguration开启自动配置功能
以前我们需要自己配置的东西,而现在SpringBoot可以自动帮我们配置 ;需要告诉SpringBoot开启自动配置功能,这样自动配置才能生效;
@Import({AutoConfigurationImportSelector.class}) :给容器导入组件
@AutoConfigurationImportSelector :自动配置导入选择器,给容器中导入一些组件
- AutoConfigurationImportSelector.class
- ↓
- selectImports方法
- ↓
- this.getAutoConfigurationEntry(annotationMetadata)方法
- ↓
- this.getCandidateConfigurations(annotationMetadata, attributes)方法
- ↓
- 方法体:
- List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
- Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
- return configurations;
- ↓
- 在所有包名叫做autoConfiguration的包下面都有META-INF/spring.factories文件
总结原理:
- @EnableAutoConfiguration 注解内部使用
-@Import(AutoConfigurationImportSelector.**class**)来加载配置类。
- 配置文件位置:META-INF/spring.factories,该配置文件中定义了大量的配置类,当 SpringBoot 应用启动时,会自动加载这些配置类,初始化Bean
- 并不是所有的Bean都会被初始化,在配置类中使用Condition来加载满足条件的Bean
通过在配置类中使用@ConfigurationProperties注解,可以将配置文件中的属性值自动绑定到配置类的属性上。以导入Redis为例
RedisProperties
- @ConfigurationProperties(prefix = "spring.redis")
- public class RedisProperties {
- private String host="localhost";
- private int port=6379;
-
- public String getHost() {
- return host;
- }
-
- public void setHost(String host) {
- this.host = host;
- }
-
- public int getPort() {
- return port;
- }
-
- public void setPort(int port) {
- this.port = port;
- }
- }
主配置类中自动加载RedisProperties
- @Configuration
- @EnableConfigurationProperties(RedisProperties.class)
- public class RedisAutoconfiguration {
- //注入jedis
- //@ConditionalOnBean
- @Bean
- public Jedis jedis(RedisProperties redisProperties){
- return new Jedis(redisProperties.getHost(),redisProperties.getPort());
- }
- }
通过在配置类或Bean上使用@Conditional注解,可以根据条件来决定是否应用某个配置或创建某个Bean。
- ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean
- ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean
- ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean
- ConditionalOnBean:判断环境中有对应Bean才初始化Bean
以导入Jedis坐标后创建Bean为例,基本思路是:判断redis.clients.jedis.Jedis.class文件是否存在
- public class ClassCondition implements Condition {
- /**
- *
- * @param context 上下文对象。用于获取环境,IOC容器,ClassLoader对象
- * @param metadata 注解元对象。 可以用于获取注解定义的属性值
- * @return
- */
-
- @Override
- public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
- //1.需求: 导入Jedis坐标后创建Bean
- //思路:判断redis.clients.jedis.Jedis.class文件是否存在
- boolean flag = true;
- try{
- Class<?> cls = Class.forName("redis.clients.jedis.Jedis");
- } catch (ClassNotFoundException e) {
- flag = false;
- }
- return flag;
- }
- }
- @Configuration
- public class UserConfig {
-
- @Bean
- @Conditional(value = ClassCondition.class)
- public User user(){
- return new User();
- }
- }
- @SpringBootApplication
- public class DemoApplication {
-
- public static void main(String[] args) {
- ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
- //获取Bean,redisTemplate
- //情况1 没有添加坐标前,发现为空
- //情况2 有添加坐标前,发现有对象
- // Object redisTemplate = context.getBean("redisTemplate");
- // System.out.println(redisTemplate);
-
- /********************案例1********************/
- Object user = context.getBean("user");
- System.out.println(user);
- }
-
- }
通过引入Spring Boot Starter依赖,可以自动配置相关的功能。例如,引入spring-boot-starter-web依赖可以自动配置Web应用程序所需的相关功能。可以在模块中引入自定义的配置。
- <!--引入自定义的redis-spring-boot-autoconfigure-->
- <dependency>
- <groupId>com.apesource</groupId>
- <artifactId>redis-spring-boot-autoconfigure</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </dependency>
实现步骤
- 创建redis-spring-boot-autoconfigure模块
- 创建redis-spring-boot-starter模块,依赖redis-spring-boot-autoconfigure的模块
- 在redis-spring-boot-autoconfigure模块中初始化Jedis的Bean,并定义META-INF/spring.factories文件
- 在测试模块中引入自定义的redis-starter依赖,测试获取Jedis的Bean,操作redis。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。