SpringBoot |
您所在的位置:网站首页 › springboot的底层 › SpringBoot |
SpringBoot-11-JDBC
SpringData简介 对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 底层都是采用 Spring Data 的方式进行统一处理。 Spring Data 官网 查看数据库相关的启动器 :官方文档 整合JDBC 1.创建一个新项目:springboot-04-jdbc,引入相应的模块
运行结果 可以通过修改配置文件来修改数据源 实现如下: spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC username: root password: root # 修改默认数据源 type: org.springframework.jdbc.datasource.DriverManagerDataSource运行结果 Spring Boot版本2.2.5默认使用HikariDataSource作为数据源,而以前版本 如Spring Boot版本1.5默认使用 org.apache.tomcat.jdbc.pool.DataSource 作为数据源。 HikariDataSource 号称 Java WEB 当前速度最快的数据源,相比于传统的 C3P0 、DBCP、Tomcat jdbc 等连接池更加优秀; 可以spring.datasource.type 指定自定义的数据源类型,值为 要使用的连接池实现的完全限定名。 分析原理 SpringBoot 几乎所有的默认配置都是通过配置类XxxAutoConfiguration进行配置,Spring Boot 的数据源也不例外,它的自动配置类是DataSourceAutoConfiguration 在/META-INF/spring.factories文件找到DataSourceAutoConfiguration配置类
DataSourceAutoConfiguration共包括5个内部配置类 EmbeddedDatabaseConditionPooledDataSourceAvailableConditionPooledDataSourceConfigurationPooledDataSourceConfiguration(池化数据源自动配置类)EmbeddedDatabaseConfiguration(内嵌数据源自动配置类)其中,PooledDataSourceConfiguration和EmbeddedDatabaseConfiguration为使用了@Configuration注解的自动配置类,其余三个为限定条件类。 EmbeddedDatabaseConfiguration @Configuration(proxyBeanMethods = false) @Conditional(EmbeddedDatabaseCondition.class) //容器汇总没有数据源的配置类下生效 @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import(EmbeddedDataSourceConfiguration.class) protected static class EmbeddedDatabaseConfiguration { }EmbeddedDatabaseConfiguration是内嵌的数据源配置类,类中没有任何方法实现,主要的功能是通过@Import注解引入EmbeddedDataSourceConfiguration类实现的 @Import(EmbeddedDataSourceConfiguration.class)点击EmbeddedDataSourceConfiguration @Configuration(proxyBeanMethods = false) //开启配置属性,绑定DataSourceProperties类 @EnableConfigurationProperties(DataSourceProperties.class) public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware { private ClassLoader classLoader; @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } //向容器中添加 Spring Boot 内嵌的数据源 @Bean(destroyMethod = "shutdown") public EmbeddedDatabase dataSource(DataSourceProperties properties) { return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseConnection.get(this.classLoader).getType()) .setName(properties.determineDatabaseName()).build(); } }通过上面的分析,可知自动配置类 EmbeddedDatabaseConfiguration 的作用是向容器中添加一个内嵌的数据源(DataSource),但这是有条件限制的。 条件限制: @Conditional(EmbeddedDatabaseCondition.class) protected static class EmbeddedDatabaseConfiguration { }EmbeddedDatabaseConfiguration类上使用一个@Conditional注解,该注解使用了 DataSourceAutoConfiguration 的内部限制条件类 EmbeddedDatabaseCondition 来进行条件判断。 说明: EmbeddedDatabaseCondition主要用来检测容器中是否已经存在池化数据源(PoolDataSource)。若容器中存在池化数据源时,则EmbeddedDatabaseConfiguration不能被实例化。只有当容器不存在池化数据源时,EmbeddedDatabaseConfiguraion才能被实例化,才能向容器中添加内嵌数据源(EmbeddedDataSource) public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { ConditionMessage.Builder message = ConditionMessage.forCondition("EmbeddedDataSource"); if (hasDataSourceUrlProperty(context)) { return ConditionOutcome.noMatch(message.because(DATASOURCE_URL_PROPERTY + " is set")); } if (anyMatches(context, metadata, this.pooledCondition)) { return ConditionOutcome.noMatch(message.foundExactly("supported pooled data source")); } EmbeddedDatabaseType type = EmbeddedDatabaseConnection.get(context.getClassLoader()).getType(); if (type == null) { return ConditionOutcome.noMatch(message.didNotFind("embedded database").atAll()); } return ConditionOutcome.match(message.found("embedded database").items(type)); }PooledDataSourceConfiguration @Configuration(proxyBeanMethods = false) @Conditional(PooledDataSourceCondition.class) @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class, DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class }) protected static class PooledDataSourceConfiguration { }PooledDataSourceConfiguration 是池化数据源的自动配置类,通过@Conditional注解可知,该注解使用DataSourceAutoConfiguration的内部限制条件类PooledDataSourceCondition来进行条件判断。 PooledDataSourceCondition 与 EmbeddedDatabaseCondition 一样,也是用来检测容器中是否已经存在池化数据源的,但不同的是,PooledDataSourcceConfiguraion只有当容器存在池化数据源时,才可以被实例化,才可以向容器中添加池化数据源。 与 EmbeddedDatabaseConfiguration 一样,PooledDataSourceConfiguration 类中也没有任何的方法实现,它的所有功能都是通过 @Import 注解引入其他的类实现的。 PooledDataSourceConfiguration 通过 @Import 注解引入了 Hikari、Tomcat、Dbcp2、OracleUcp 和 Generic 五个数据源配置类,它们都是 DataSourceConfiguration 的内部类,且它们的功能类似,都是向容器中添加指定的数据源。 以 Hikari 为例进行分析 @Configuration(proxyBeanMethods = false) //表示这是一个配置类 @ConditionalOnClass(HikariDataSource.class) //表示必须类路径下存在HikariDataSource类,这个配置类才会被实例化 //HikariDataSource 类是由 spring- boot-starter-jdbc 默认将其引入的,因此只要我们在 pom.xml 中引入了该 starter, Hikari 就会被实例化 @ConditionalOnMissingBean(DataSource.class) //容器中没有DataSource这个类,才会被实例化 @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true) //Spring Boot配置文件时,配置了spring.datasource.type=com.zaxxer.hikari.HikariDataSource或者不配置spring.datasource.tyoe时,Hikari才会被实例化 static class Hikari { @Bean // 与配置文件名为spring.datasource.hikari下的所有属性绑定 @ConfigurationProperties(prefix = "spring.datasource.hikari") HikariDataSource dataSource(DataSourceProperties properties) { HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class); if (StringUtils.hasText(properties.getName())) { dataSource.setPoolName(properties.getName()); } return dataSource; } }Hikari类通过@Bean注解向容器中添加了HikariDataSource组件,该组件的实例对象是通过调用DataSourceConfiguration的createDataSource()方法得到的 createDataSource() protected static T createDataSource(DataSourceProperties properties, Class type) { return (T) properties.initializeDataSourceBuilder().type(type).build(); }DataSourceProperties类
调用了DataSourceProperties的initializeDataSourceBuilder()初始化DataSourceBuilder initializeDataSourceBuilder() public DataSourceBuilder initializeDataSourceBuilder() { return DataSourceBuilder.create(getClassLoader()).type(getType()).driverClassName(determineDriverClassName()) .url(determineUrl()).username(determineUsername()).password(determinePassword()); }initialDataSourceBuilder()方法通过调用DataSourceBulider的create()方法,将application.properties/yaml的配置,依次设置数据源类型、驱动类名、连接 url、 用户名和密码等信息。 sprIng.datasource.type默认是不用配置的。createDataSource() 方法在获取到回传回来的 DataSourceBuilder 对象后,还需要将其 type 属性再次设置为 HikariDataSourcee,并调用 DataSourceBuilder 的 build() 方法,完成 HikariDataSource 的初始化。 protected static T createDataSource(DataSourceProperties properties, Class type) { return (T) properties.initializeDataSourceBuilder().type(type).build(); }dataSource() 方法获得数据源对象,并设置了连接池的名字(name),注入到容器中。 总结: 用户没有配置数据源的情况,若容器中存在 HikariDataSource 类,则 Spring Boot 就会自动实例化 Hikari,并将其作为其数据源。Spring Boot 的 JDBC 场景启动器(spring-boot-starter-data-jdbc)通过 spring- boot-starter-jdbc 默认引入了 HikariCP 数据源(包含 HikariDataSource 类),因此 Spring Boot 默认使用 HikariCP 作为其数据源。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |