学习Springboot之前,肯定要有javaweb、Spring的基础,在没有接触Springboot的时候,并不能体会Springboot的简便,但是Springboot确实很火,就花了时间学习了一下,发现开箱即用,几乎不需要配置。既然SpringBoot的核心是Spring,为什么Spring的配置都不需要了呢?跟着百度,糊里糊涂的了解了一下,只是了解了一下思路...
疑惑一:自动配置
- Springboot是如何让我们不需要配置,就可以使用呢?
最重要的还是@SpringBootApplication注解,这个注解标注为该类是一个应用的启动类,点开之后,发现是一个复合注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {}
- @ComponentScan:这个注解是组件扫描这个是我们最熟悉的注解,即使没有使用过注解也经常在spring的配置文件中使用过<context:component-scan base-package="com.xxx.xxx"/>, 组件扫描就是扫描指定的包下的类,并加载符合条件的组件。
- @SpringBootConfiguration:其实就是一个@Configuration,表明这是一个配置类
- @EnableAutoConfiguration:这是自动配置最重要的一个注解了,开启自动配置功能,以前需要自动配置的东西,Spring Boot帮我们自动配置
@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 {};
}
@AutoConfigurationPackage:将主配置类所在的包下的所有组件,添加到Spring容器中
,这也就是为什么不需要我们配置的原因了,Springboot帮我们配置好了
疑惑二:自动配置条件
参考DataSourceConfiguration,
数据源有三个配置,不可能将三个都加载到容器中,这时候@Conditional条件判断就起作用了:
@Configuration(proxyBeanMethods = false)
// tomcat自带的datasource连接池,由于默认情况下spring-boot未引入org.apache.tomcat.jdbc.pool.DataSource对应的依赖包,
// 根据@ConditionalOnClass注解的作用,这个配置不会生效
@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource",
matchIfMissing = true)
static class Tomcat {}
// 这是SpringBoot默认的数据源
/**
* Hikari DataSource configuration.
*/
@Configuration(proxyBeanMethods = false)
// 存在这个class,继续执行
@ConditionalOnClass(HikariDataSource.class)
// 如果不存在数据源bean,才继续执行,如果我们添加Druid数据源,此处就不在继续执行
@ConditionalOnMissingBean(DataSource.class)
// 配置文件中存在spring.datasource.type,且为com.zaxxer.hikari.HikariDataSource,或者不存在这个属性的时候,继续执行
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
matchIfMissing = true)
static class Hikari {}
/**
* DBCP DataSource configuration.
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(org.apache.commons.dbcp2.BasicDataSource.class)
// 上一步已经加载了DataSource,这一步不再执行
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp2.BasicDataSource",
matchIfMissing = true)
static class Dbcp2 {}
/**
* Generic DataSource configuration.
*/
// 如果配置了Druid或其他数据源,会创建默认的Bean,否则跳过
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {
@Bean
DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
从上面的代码可以知道spring-boot默认实现了hikari连接池,我们如果想更换为Druid连接池,只需要引入相应的连接池,并spring.datasource.type配置为Druid的类,所以Springboot会根据各种条件,来确保只有一项可以生效。
参考自:
https://blog.csdn.net/song_java/article/details/86509971
https://github.com/lxy-go/SpringBoot