一、什么是springboot的自动配置?
Spring Boot通过@EnableAutoConfiguration注解开启自动配置,对autoconfigured的jar包下的META-INF下的spring包中下的spring.factories文件进行扫描,这个文件中包含了可以进行自动配置的类,当满足@Condition注解指定的条件时,便在依赖的支持下进行实例化,注册到Spring容器中。 用注解来对一些常规的配置做默认配置,简化了各种xml配置内容,使项目能够快速运行。自动装配最明显的特征就是不用xml文件去做配置,而是用到properties文件或者yml文件,在pom.xml中简单地写一些坐标就能实现各类负载地配置。自动将Bean装配到IOC容器中
二、@Enable注解
SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注解导入一些配置类,实现Bean的动态加载
思考** SpringBoot 工程是否可以直接获取jar包中定义的Bean****? **
**@Import****注解 **
@Enable底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。 而@Import提供4中用法:
① 导入Bean
② 导入配置类
③ 导入 ImportSelector 实现类。一般用于加载配置文件中的类
④ 导入 ImportBeanDefinitionRegistrar 实现类。
//MyImportSelector
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//目前字符串数组内容是写死的,未来可以设置在配置文件中动态加载
return new String[]{"com.apesource.springbootenableother04.domain.User","com.apesource.springbootenableother04.domain.Student"};
}
}
//MyImportBeanDefinitionRegistrar
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//AnnotationMetadata注解
//BeanDefinitionRegistry向spring容器中注入
//获取user的definition对象
AbstractBeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
//通过beanDefinition属性信息,向Spring容器中注册id为user的对象
registry.registerBeanDefinition("user",beanDefinition);
}
}
//UserConfig
@Configuration
public class UserConfig {
@Bean
public User user(){
return new User();
}
}
//EnableUser
@Target(value = ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(UserConfig.class)
public @interface EnableUser {
}
三、springboot自动配置流程
springboot的启动类main方法上有一个springboot的核心注解**@SpringbootApplication**
按ctrl点进去
**@ComponentScan **
这个注解在Spring中很重要 ,它对应XML配置中的元素。
作用:自动扫描并加载符合条件的组件或者bean , 将这个bean定义加载到IOC容器中
**@SpringBootConfiguration **
作用:SpringBoot的配置类 ,标注在某个类上 , 表示这是一个SpringBoot的配置类;
@EnableAutoConfiguration注解
主要作用是开启自动配置
而@EnableAutoConfiguration也是一个复合注解,它包含了@AutoConfigurationPackage和@Import({AutoConfigurationImportSelector.class})。
@AutoConfigurationPackage注解,自动配置包。点进去可以看到就是⼀个 @Import 注解:@Import(Registrar.class) ,导⼊了⼀个Registrar 的组件,这个注解的作用就是将主配置类(@SpringBootConfiguration标注的类)所在的包及其下面所有子包里面所有的组件扫描到IOC容器中。
而@Import(AutoConfigurationImportSelector.class)注解通过@Import导入了AutoConfigurationImportSelector类,而这个类的selectImports方法会通过SpringFactoriesLoader(这个类实现了检索META-INF/spring.factories文件,并获取指定接口的配置的功能)得到大量的配置类,当 SpringBoot 应用启动时,会自动加载这些配置类,初始化Bean 。而每个配置类则根据条件化配置类做出决策,以实现自动配置的功能。
SpringFactoriesLoader
机制:Spring Boot 在META-INF/spring.factories
文件中定义了自动配置类的列表。在启动时,通过SpringFactoriesLoader
加载这些配置类,并根据条件进行处理。
我们写配置类只需要加入一个@Configuration注解,Springboot就可以轻松地自己找到想要地目标文件。
并不是所有的Bean都会被初始化,需要在配置类中使用Condition来加载满足条件的Bean
condition的几个注解:
ConditionalOnProperty:用来判断配置文件中是否有对应属性和值才初始化Bean
ConditionalOnClass:用来判断环境中是否有对应字节码文件才初始化Bean
ConditionalOnMissingBean:用来判断环境中没有对应Bean才初始化Bean
ConditionalOnBean:用来判断环境中有对应Bean才初始化Bean
综上所述大概就是:
Spring Boot 的
自动配置流程大致如下:
启动应用:当运行 Spring Boot 应用时,首先会
加载主启动类。依赖解析:Spring Boot 会检查项目中引入的依赖。
加载
spring.factories
文件:查找并加载META-INF/spring.factories
文件,该文件中定 义了各种自动配置类。条件判断:对于每个自动配置类,根据条件注解(如
@ConditionalOnClass
、@ConditionalOnProperty
等)进行判断。- 如果条件满足,相关的配置类会被加载。 - 如果条件不满足,则跳过该配置。
配置生效:满足条件的配置类中的配置逻辑被执行,完成相关组件的自动配置。
应用上下文准备:将自动配置好的组件注册到 Spring 应用上下文 (ApplicationContext) 中,使其可供应用使用。
启动完成:完成自动配置和组件注册后,应用启动完成,开始处理业务逻辑。
例如,如果项目中添加了数据库相关的依赖,并且配置文件中提供了正确的数据库连接信息,那么相应的数据库自动配置类会在条件满足的情况下被加载和执行,完成数据库连接池等的配置。
四、自定义启动类
**需求: **
自定义redis-starter,要求当导入redis坐标时,SpringBoot自动创建Jedis的Bean
**参考: **
可以参考mybatis启动类的应用
**实现步骤: **
**1、创建redis-spring-boot-autoconfigure模块 **
**2、创建redis-spring-boot-starter模块,依赖redis-spring-boot-autoconfigure的模块 **
<!--引入自定义的redis-spring-boot-autoconfigure-->
<dependency>
<groupId>com.apesource</groupId>
<artifactId>redis-spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
3、在redis-spring-boot-autoconfigure模块中初始化Jedis的Bean,并定义META
**INF/spring.factories文件 **
redis-spring-boot-autoconfigure的pom.xml文件中:
<!--引入jedis依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
spring.factories文件:
根据springboot自动配置的过程,我们手动的配置了一个spring.factories用来设置自动加载类是谁
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.apesource.RedisAutoconfiguration
RedisProperties类:(定义主机和端口号)
import org.springframework.boot.context.properties.ConfigurationProperties;
@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;
}
}
这里面的@ConfigurationProperties(prefix = "spring.redis")用于将外部配置文件,就比如 application.properties 或 application.yml中的配置参数绑定到这个类的字段上。 host是Redis服务器的主机名,port是于存储 Redis 服务器的端口号。
RedisAutoConfiguration类:(配置类)
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoconfiguration {
//注入jedis
@Bean
public Jedis jedis(RedisProperties redisProperties){
return new Jedis(redisProperties.getHost(), redisProperties.getPort());
}
}
加了@EnableConfigurationProperties(RedisProperties.class)注解用于对对 RedisProperties 配置属性类的支持。RedisProperties 是一个包含了 Redis 配置参数的类,通常包括主机名、端口等。通过这个注解,Spring Boot 可以将外部配置文件(如 application.properties 或 application.yml)中的相关配置映射到 RedisProperties 类的属性中,并自动实例化一个 RedisProperties 对象。
**4、在测试模块中引入自定义的redis-starter依赖,测试获取Jedis的Bean,操作redis。 **
<!--引入自定义的redis-spring-boot-starter模块-->
<dependency>
<groupId>com.apesource</groupId>
<artifactId>redis-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
properties.yml文件中自定义配置redis的主机和端口号
spring:
redis:
host: 127.0.0.1
port: 6060
测试类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import redis.clients.jedis.Jedis;
@SpringBootApplication
public class SpringbootStarter04Application {
public static void main(String[] args) {
ConfigurableApplicationContext context=SpringApplication.run(SpringbootStarter04Application.class, args);
Jedis bean1=context.getBean(Jedis.class);
System.out.println(bean1);
}
}
运行结果:
版权归原作者 Z_DOUBLE_Y 所有, 如有侵权,请联系我们删除。