SpringBoot 自动配置和启动类

SpringBoot 自动配置和启动类

自动装配

传统 Spring 整合其他的包的步骤

  1. 读取配置文件
  2. 装配Bean的Config
  3. 导入主配置类

SpringBoot 整合其他的包的步骤

这会发现一个问题,如果每一次创建 Spring 项目都需要写配置类,会导致效率下降。
而配置类大部分都是固定的创建Bean的流程,无非就是具体配置不同而已。
SpringBoot 提供的基于 SPI 完成的自动配置可以解决这个问题

  1. 读取配置可以通过 SpringBoot 提供 @ConfigurationProperties 注解完成读取,读取的配置存放到 XXXProperties 中
  2. 将 XXXProperties 注入到 XXXAutoConfig,通过注入的Properties类完成创建 Bean 的流程
  3. 通过 spring.factories 配置文件注入到 SpringBoot 的自动配置类中

Application启动类介绍

Application启动类,同时也是配置类
上面的复合注解 @SpringBootApplication

表示一个configuration类,声明一个或多个@Bean方法,同时触发auto-configuration和component scanning 。这是一个方便的注释,相当于声明@SpringBootConfiguration 、 @EnableAutoConfiguration和@ComponentScan 。

自动配置类介绍

为什么不需要用于整合的配置类,因为SpringBoot有自动配置类
现在不需要装配一些常见的配置类,因为常见的依赖都有自动配置的包,比如mybatis-spring-boot-starter依赖了mybatis-spring-boot-autoconfigure
而Application启动类上的注解 @SpringBootApplication 触发了自动装配的操作

@SpringBootApplication

@SpringBootApplication中有
@SpringBootConfiguration 声明配置类
@EnableAutoConfiguration 启用自动配置的关键,它导入了一个AutoConfigurationImportSelectord的自动配置选择器,在这个选择器中利用SpringFactoriesLoader(框架内部使用的通用工厂装载机制)读取了META-INF/spring.factories的文件
@EnableAutoConfiguration里面有@Import(AutoConfigurationImportSelector.class) 导入了类自动配置导入选择器

SpringBoot整合案例

C3p0DataSourceProperties.java

@Data
/**
 * 将yml配置的属性绑定到这个类中 使用松散绑定
 * 外部化配置的注释。如果您想绑定和验证一些外部属性(例如,从.Properties文件),请将其添加到类定义或@Configuration类中的@Bean方法中。
 * 绑定可以通过调用带注释类上的setter来执行,也可以通过绑定到构造函数参数来执行,如果@ConstructorBinding正在使用中。
 * 请注意,与@Value相反,由于属性值是外部化的,因此不会计算SpEL表达式。
 */
@ConfigurationProperties(prefix = "spring.datasource.c3p0")
public class C3p0DataSourceProperties {
    // 驱动类名
    private String driverClassName;
    // 数据库连接地址
    private String url;
    // 用户名
    private String userName;
    // 密码
    private String password;
    // 最小连接池大小
    private Integer minPoolSize;
    // 最大连接池大小
    private Integer maxPoolSize;
    // 初始连接池大小
    private Integer initialPoolSize;
    // 最大空闲时间
    private Integer maxIdleTime;
}

C3p0DataSourceAutoConfigure.java

@Configuration
//@ConditionalXxx的都是spring提供的条件注解,这些注解的作用
//就是当满足某个条件的时候才会执行装配
//例如@ConditionalOnClass,它表示当classpath中存在
//ComboPooledDataSource(C3P0核心连接池)这个类的时候
//才会初始化当前的配置类
@ConditionalOnClass(ComboPooledDataSource.class)
//这个注解表示当前的配置类在DataSourceAutoConfiguration之前
//加载并初始化
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
//将带有@ConfigurationProperties注解的类纳入Spring的IOC容器中
//以便于在任何地方可以进行注入
@EnableConfigurationProperties(C3p0DataSourceProperties.class)
public class C3p0DataSourceAutoConfigure {

    /**
     * 注入CP30的配置属性
     */
    private C3p0DataSourceProperties properties;

    @Autowired
    public void setProperties(C3p0DataSourceProperties properties) {
        this.properties = properties;
    }

    @Bean
    //这个条件注解标识当容器中存在这个Bean的时候才会执行装配
    //@ConditionalOnBean
    //这个条件注解标识当容器中不存在这个Bean的时候才会执行装配
    @ConditionalOnMissingBean
    public DataSource dataSource() throws PropertyVetoException {
        //创建C3P0的数据源
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //将配置属性设置到dataSource中
        dataSource.setDriverClass(properties.getDriverClassName());
        dataSource.setJdbcUrl(properties.getUrl());
        dataSource.setUser(properties.getUserName());
        dataSource.setPassword(properties.getPassword());
        dataSource.setMinPoolSize(properties.getMinPoolSize());
        dataSource.setMaxPoolSize(properties.getMaxPoolSize());
        dataSource.setInitialPoolSize(properties.getInitialPoolSize());
        dataSource.setMaxIdleTime(properties.getMaxIdleTime());
        return dataSource;
    }

}

spring.factories

# 启用Spring应用程序上下文的自动配置,尝试猜测和配置您可能需要的bean
org.springframework.boot.autoconfigure.EnableAutoConfiguration = \
  org.c3p0.spring.boot.autoconfigure.C3p0DataSourceAutoConfigure