springboot2.0整合druid,以及springboot自动装配DataSource原理

1.springboot 目前的推荐版是2.1.2.RELEASE,我们就以当前最新的推荐版为例

2.创建项目,引入对应的jar包,我是以maven的形式

父级的pom

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

 引入的包

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

3.配置文件,更新详细的配置 请参考 阿里的github查看,网址;里面介绍了更详细的属性含义,以及多数据源的配置方式

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 8
      min-idle: 1
      max-active: 20
      max-wait: 60000
      time-between-eviction-runsMillis: 60000
      min-evictable-idle-timeMillis: 300000
      validation-query: select 'x' FROM DUAL
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true
      max-open-prepared-statements: 20
      max-pool-prepared-statement-per-connection-size: 20
      filters: stat
      connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      use-global-data-source-stat: true

4.测试类,debug运行,可以看到,DataSource接口的实现类就是durid的实现类,可以继续找到配置文件中的一些初始化参数

      initial-size: 8
      min-idle: 1
      max-active: 20
      max-wait: 60000

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { BadgerDruidApplication.class })
public class BadgerDruidApplicationTests {

    @Autowired
    DataSource dataSource;

    @Test
    public void contextLoads() throws SQLException {
        Connection connection = dataSource.getConnection();
        PreparedStatement prepareStatement = connection
                .prepareStatement("select * from t_city where parent_id='-1'");
        ResultSet resultSet = prepareStatement.executeQuery();
        while (resultSet.next()) {
            String cityName = resultSet.getString("name");
            System.out.println(cityName);
        }
    }
}

至此,druid就与springboot2.0集成完成了;当然中间也会有springboot2.0 mysql的驱动包,跟服务端版本不匹配的异常

java.sql.SQLNonTransientConnectionException: CLIENT_PLUGIN_AUTH is required

替换下mysql驱动的版本

<properties>
        <java.version>1.8</java.version>
        <mysql.version>5.1.6</mysql.version>
    </properties>

5.下面讲一点springboot对DataSource的一些自动装配原理,以及另一种druid的方式

spring-boot-autoconfigure-2.1.2.RELEASE.jar包下的org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration类

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
		DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {

	@Configuration
	@Conditional(EmbeddedDatabaseCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import(EmbeddedDataSourceConfiguration.class)
	protected static class EmbeddedDatabaseConfiguration {

	}

	@Configuration
	@Conditional(PooledDataSourceCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
			DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
			DataSourceJmxConfiguration.class })
	protected static class PooledDataSourceConfiguration {

	}

	/**
	 * {@link AnyNestedCondition} that checks that either {@code spring.datasource.type}
	 * is set or {@link PooledDataSourceAvailableCondition} applies.
	 */
	static class PooledDataSourceCondition extends AnyNestedCondition {

		PooledDataSourceCondition() {
			super(ConfigurationPhase.PARSE_CONFIGURATION);
		}

		@ConditionalOnProperty(prefix = "spring.datasource", name = "type")
		static class ExplicitType {

		}

		@Conditional(PooledDataSourceAvailableCondition.class)
		static class PooledDataSourceAvailable {

		}

	}

我们先看类上@Import({ DataSourcePoolMetadataProvidersConfiguration.class,DataSourceInitializationConfiguration.class })

DataSourcePoolMetadataProvidersConfiguration导入这个类的实例,点进去可以看到

@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)

@ConditionalOnClass(HikariDataSource.class)

@ConditionalOnClass(BasicDataSource.class)

这3个数据源的装配,都是导入了这些数据源,才会实例创建成功;而springboot2.0的默认生效的HikariDataSource数据源;如图所示,spring-boot-starter-jdbc默认依赖了;而在springboot1.x中,默认生效的org.apache.tomcat.jdbc.pool.DataSource.class

 

现在我们看下根据spring.datasource.type指定类型的实例化,只拿了一部分主要的,我们主要来看PooledDataSourceConfiguration 这个内部类

    @Configuration
	@Conditional(PooledDataSourceCondition.class)
	@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
	@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
			DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
			DataSourceJmxConfiguration.class })
	protected static class PooledDataSourceConfiguration {

	}
	

@Conditional(PooledDataSourceCondition.class) 根据判断条件,实例化这个类,指定了配置文件中,必须有type这个属性

实例化后,@Import 会导入DataSourceConfiguration 这个类;在DataSourceConfiguration这个类中,就是具体的DataSource接口实现;我们默认导入web模块后,会导入tomcat,并且实例化org.apache.tomcat.jdbc.pool.DataSource

	/**
	 * Tomcat Pool DataSource configuration.
	 */
	 //只要导入了这个org.apache.tomcat.jdbc.pool.DataSource.class,就会生效
	@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
	//没有DataSource的实例
	@ConditionalOnMissingBean(DataSource.class)
	//配置了spring.datasource.type 并且值为org.apache.tomcat.jdbc.pool.DataSource,才会生效;
	//matchIfMissing=true表示,就算没有配置spring.datasource.type,也会生效
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true)
	static class Tomcat {

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.tomcat")
		public org.apache.tomcat.jdbc.pool.DataSource dataSource(
				DataSourceProperties properties) {
			org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(
					properties, org.apache.tomcat.jdbc.pool.DataSource.class);
			DatabaseDriver databaseDriver = DatabaseDriver
					.fromJdbcUrl(properties.determineUrl());
			String validationQuery = databaseDriver.getValidationQuery();
			if (validationQuery != null) {
				dataSource.setTestOnBorrow(true);
				dataSource.setValidationQuery(validationQuery);
			}
			return dataSource;
		}

	}

另外springboot 默认支持 type 类型设置的数据源;

@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
            DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.Generic.class,
            DataSourceJmxConfiguration.class })

具体的,接着DataSourceConfiguration类看就可以了,

下面说下,集成druid 在DataSourceConfiguration类,最后的部分

	/**
	 * Generic DataSource configuration.
	 */
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type")
	static class Generic {

		@Bean
		public DataSource dataSource(DataSourceProperties properties) {
			return properties.initializeDataSourceBuilder().build();
		}

	}

如果上面,都不生效,就会执行这个;我们直接看 return properties.initializeDataSourceBuilder().build(); 这个build方法;

@SuppressWarnings("unchecked")
	public T build() {
		Class<? extends DataSource> type = getType();
		DataSource result = BeanUtils.instantiateClass(type);
		maybeGetDriverClassName();
		bind(result);
		return (T) result;
	}

拿到上述配置文件中的com.alibaba.druid.pool.DruidDataSource 这个类的全类名,反射实例化;至此,datasource的实例过程,就说完了;最后我们看下,阿里官方封装的druid-spring-boot-starter,直接简单粗暴的创建了一个datasource的实现,有感性的朋友,也可以看下DruidDataSourceWrapper 的具体实现,就不在继续描述

@Configuration
@ConditionalOnClass(DruidDataSource.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class,
    DruidStatViewServletConfiguration.class,
    DruidWebStatFilterConfiguration.class,
    DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {

    private static final Logger LOGGER = LoggerFactory.getLogger(DruidDataSourceAutoConfigure.class);

    @Bean(initMethod = "init")
    @ConditionalOnMissingBean
    public DataSource dataSource() {
        LOGGER.info("Init DruidDataSource");
        return new DruidDataSourceWrapper();
    }
}

 

 

  • 13
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
Spring Boot项目中整合Druid和MyBatis Plus可以提供非常好的数据库访问性能和可维护性。下面是一些简单的步骤: 1. 添加依赖 在pom.xml中添加以下依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>{druid-version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>{mybatis-plus-version}</version> </dependency> ``` 2. 配置数据源 在application.properties或application.yml文件中添加以下配置: ```yml spring: datasource: url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource # druid 连接池配置 druid: initial-size: 2 min-idle: 1 max-active: 20 max-wait: 60000 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 validation-query: SELECT 1 FROM DUAL test-while-idle: true test-on-borrow: false test-on-return: false pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 filters: stat, wall, log4j connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 ``` 3. 配置MyBatis Plus 在配置类中添加以下配置: ```java @Configuration @MapperScan("com.example.mapper") public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } } ``` 这里使用了MyBatis Plus的分页插件。 4. 创建Mapper 创建Mapper接口并使用MyBatis Plus的注解: ```java @Mapper public interface UserMapper extends BaseMapper<User> { } ``` 5. 测试 创建Controller并测试: ```java @RestController @RequestMapping("/users") public class UserController { @Autowired private UserMapper userMapper; @GetMapping("") public List<User> list() { return userMapper.selectList(null); } } ``` 这样就完成了Druid和MyBatis Plus的整合

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

葵花下的獾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值