SpringBoot自动配置原理

目录

Conditional

@Enable注解

@EnableAutoConfiguration 注解

总结原理

自定义启动器


SpringBoot 的核心优势之一是 "自动配置"(Auto-configuration),它让开发者无需手动编写大量 XML 或 Java 配置就能快速搭建应用。本文将从底层原理出发,详细拆解自动配置的实现机制。

Conditional

条件化注解(如@ConditionalOnClass, @ConditionalOnBean等):这类注解允许开发者定义特定条件下才激活的配置规则。例如,只有当指定类存在于当前类路径下时,相关的bean才会被创建和配置,从而实现更加灵活且针对性强的自动配置策略。

自定义条件:

① 定义条件类:自定义类实现Condition接口,重写 matches 方法,在 matches 方法中进行逻辑判 断,返回 boolean值 。

matches 方法两个参数:

• context:上下文对象,可以获取属性值,获取类加载器,获取BeanFactory等。

• metadata:元数据对象,用于获取注解属性。

② 判断条件: 在初始化Bean时,使用 @Conditional(条件类.class)注解

SpringBoot 提供的常用条件注解: 以下注解在springBoot-autoconfigure的condition包下 ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean ConditionalOnBean:判断环境中有对应Bean才初始化Bean

@Enable注解

SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注 解导入一些配置类,实现Bean的动态加载

@Import注解

@Enable底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。 而@Import提供4中用法:

① 导入Bean

② 导入配置类

③ 导入 ImportSelector 实现类。一般用于加载配置文件中的类

④ 导入 ImportBeanDefinitionRegistrar 实现类。

@EnableAutoConfiguration 注解

主启动类

//@SpringBootApplication 来标注一个主程序类
//说明这是一个Spring Boot应用
@SpringBootApplication
public class SpringbootApplication {
   public static void main(String[] args) {
     //以为是启动了一个方法,没想到启动了一个服务
      SpringApplication.run(SpringbootApplication.class, args);
   }
}

@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可以自动帮我们配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效。

@Import({AutoConfigurationImportSelector.class}) :给容器导入组件 ;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})//给容器导入组件
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}
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。

自定义启动器

需求: 自定义datasource-starter,要求当导入其坐标时,SpringBoot自动创建DataSource的Bean

实现步骤:

创建datasource_springboot_autoconfig模块

创建datasource_springboot_starter模块,依赖datasource_springboot_autoconfig的模块

在datasource_springboot_autoconfig模块中初始化datasource,并定义META-INF/spring.factories文件 在测试模块中引入自定义的datasource_springboot_starter依赖,测试获取datasource的Bean。

datasource_springboot_autoconfig目录层级:

pom.xml:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <!--c3p0-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
    </dependencies>

【注意:这里usernames和passwords故意填写错误,看是否会用到自己配置的usernames和passwords】

@ConfigurationProperties(prefix = "datasource")
public class DataSourceProperties {
    private String jdbcUrl="jdbc:mysql://127.0.0.1:3306/lzl";
    private String driverName = "com.mysql.cj.jdbc.Driver";
    private String usernames = "root1";
    private String passwords = "1234561";

    public String getJdbcUrl() {
        return jdbcUrl;
    }

    public void setJdbcUrl(String jdbcUrl) {
        this.jdbcUrl = jdbcUrl;
    }

    public String getDriverName() {
        return driverName;
    }

    public void setDriverName(String driverName) {
        this.driverName = driverName;
    }

    public String getUsernames() {
        return usernames;
    }

    public void setUsernames(String usernames) {
        this.usernames = usernames;
    }

    public String getPasswords() {
        return passwords;
    }

    public void setPasswords(String passwords) {
        this.passwords = passwords;
    }
}

@ConfigurationProperties(prefix = "datasource"):是 Spring Boot 中的一个注解,用于将配置文件(如 application.properties 或 application.yml)中以指定前缀(这里是 datasource)开头的配置项绑定到 Java 类的属性上。

@Configuration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
    @Bean
    public DataSource dataSource(DataSourceProperties dataSourceProperties){
        try {
            ComboPooledDataSource comboPooledDataSource=new ComboPooledDataSource();
            comboPooledDataSource.setJdbcUrl(dataSourceProperties.getJdbcUrl());
            comboPooledDataSource.setDriverClass(dataSourceProperties.getDriverName());
            comboPooledDataSource.setUser(dataSourceProperties.getUsernames());
            comboPooledDataSource.setPassword(dataSourceProperties.getPasswords());
            return comboPooledDataSource;
        } catch (PropertyVetoException e) {
            throw new RuntimeException(e);
        }
    }
}

@EnableConfigurationProperties(DatasourceProperties.class)用于启用指定类的 @ConfigurationProperties 功能。如果一个类使用了 @ConfigurationProperties 但未被 Spring 容器管理(例如未加 @Component),则需要通过该注解显式指定该类,使其属性能与配置文件绑定。

META-INF/spring.factories:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.ape.DataSourceAutoConfiguration

datasource_springboot_starter:

pom.xml:

springboot_starter_test:

pom.xml:

application.yml:

datasource:
  usernames: root
  passwords: 123456

启动类:

@SpringBootApplication
public class SpringbootStarter04Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(SpringbootStarter04Application.class, args);
        DataSource bean=context.getBean(DataSource.class);
        System.out.println(bean);
    }

}

输出结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值