美文网首页
springboot配置druid连接池

springboot配置druid连接池

作者: simba2019 | 来源:发表于2020-02-24 13:50 被阅读0次

    Springboot配置druid数据连接池有两种方式,比较类似,但是如果搞混了容易导致部分配置不生效。

    1.starter方式

    这种比较简单

    1.引入依赖

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.20</version>
            </dependency>
    

    2.添加属性

    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    spring.datasource.url=jdbc:mysql://localhost:3306/workflow?useUnicode=true&characterEncoding=utf-8&useSSL=false
    spring.datasource.username=workflow
    spring.datasource.password=workflow
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    
    spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
    
    spring.datasource.druid.initial-size=1
    spring.datasource.druid.max-active=20
    spring.datasource.druid.min-idle=3
    spring.datasource.druid.max-wait=60000
    spring.datasource.druid.pool-prepared-statements=true
    spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
    spring.datasource.druid.filters=stat,wall,slf4j
    spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    
    

    这样启动项目就ok了。

    注意,不需要自己添加新的数据连接池配置类DataSourceConfig。添加了之后可能会导致项目启动失败或者部分属性例如maxActive,minIdle等这些不生效,具体原理下面会说。

    3.原理

    简单说下原理,这里用到了自动装配原理。

    关键是这个类

    @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);
    
        public DruidDataSourceAutoConfigure() {
        }
    
        @Bean(
            initMethod = "init"
        )
        @ConditionalOnMissingBean
        public DataSource dataSource() {
            LOGGER.info("Init DruidDataSource");
            return new DruidDataSourceWrapper();
        }
    }
    

    @Configuration用于定义配置类,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

    @ConditionalOnClass({DruidDataSource.class})这段可以简单理解为只有当DruidDataSource.class这个类存在时候才会实例化DruidDataSourceAutoConfigure中定义的Bean。

    @AutoConfigureBefore({DataSourceAutoConfiguration.class})表示DruidDataSourceAutoConfigure要在DataSourceAutoConfiguration这个类之前加载。

    @EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})表示开启自动装配属性,不需要手动set。与注解ConfigurationProperties配合使用,ConfigurationProperties负责将配置文件中的属性放到对象对应的属性中。

    @Import({DruidSpringAopConfiguration.class, DruidStatViewServletConfiguration.class, DruidWebStatFilterConfiguration.class, DruidFilterConfiguration.class})表示把用到的资源导入到IOC容器中。在这里就表示将这几个类实例化为Bean后加载到IOC容器中。不仅可以导入类,也可以通过@ImportResource导入xml或者properties配置文件。

    然后我们看类的实现,比较简单,除了构造方法只有一个方法public DataSource dataSource(),这个方法就是返回一个数据库连接池Bean。包含了两个注解:

    @Bean( initMethod = "init" )表示返回一个Bean,同时在Bean初始化的时候要执行init这个方法。

    @ConditionalOnMissingBean简单理解就是当dataSource这个Bean不存在时候才会加载这个Bean。

    返回的Bean很简单就是new了一个DruidDataSourceWrapper对象。

    接下来看下DruidDataSourceWrapper这个类

    @ConfigurationProperties("spring.datasource.druid")
    class DruidDataSourceWrapper extends DruidDataSource implements InitializingBean {
        @Autowired
        private DataSourceProperties basicProperties;
    
        DruidDataSourceWrapper() {
        }
    
        public void afterPropertiesSet() throws Exception {
            if (super.getUsername() == null) {
                super.setUsername(this.basicProperties.determineUsername());
            }
    
            if (super.getPassword() == null) {
                super.setPassword(this.basicProperties.determinePassword());
            }
    
            if (super.getUrl() == null) {
                super.setUrl(this.basicProperties.determineUrl());
            }
    
            if (super.getDriverClassName() == null) {
                super.setDriverClassName(this.basicProperties.getDriverClassName());
            }
    
        }
    
        @Autowired(
            required = false
        )
        public void autoAddFilters(List<Filter> filters) {
            super.filters.addAll(filters);
        }
    
        public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
            try {
                super.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
            } catch (IllegalArgumentException var4) {
                super.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
            }
    
        }
    }
    

    @ConfigurationProperties("spring.datasource.druid")这个注解上面已经提到就是为了自动装配属性,装配哪些属性由括号里面的决定,这里是装配配置文件中spring.datasource.druid开头的属性。看下之前的properties文件,发现主要是数据库连接池中maxActive,minIdle等这些属性。那么就会有个问题,连接池的最基础的属性url, username,password,driverClassName这些在配置文件中不是以spring.datasource.druid开头的,那么是怎么装配呢?有两种方法:

    1. 根据上面我们说的@ConfigurationProperties("spring.datasource.druid")可以装配以spring.datasource.druid开头的属性,将properties文件中这几项的配置改为:

      spring.datasource.druid.url=jdbc:mysql://localhost:3306/workflow?useUnicode=true&characterEncoding=utf-8&useSSL=false
      spring.datasource.druid.username=workflow
      spring.datasource.druid.password=workflow
      spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
      

      类似这样。这样@ConfigurationProperties("spring.datasource.druid")注解会将属性装配进来。

    2. 我们发现不修改也会装配进来,即下面这种形式也会装配进来

      spring.datasource.url=jdbc:mysql://localhost:3306/workflow?useUnicode=true&characterEncoding=utf-8&useSSL=false
      spring.datasource.username=workflow
      spring.datasource.password=workflow
      spring.datasource.driver-class-name=com.mysql.jdbc.Driver
      

      为什么会这样呢?

      这与这个类DruidDataSourceWrapper里面的一个方法有关:afterPropertiesSet()

    afterPropertiesSet这个方法是InitializingBean接口的实现,根据名称我们就可以猜到这个类和Bean的初始化有关系。这个方法会在Bean初始化的时候执行,并且是先于init方法执行的。具体分析我们以后文章会分析,可以关注下。

    afterPropertiesSet这个方法我们看实现就是为了把url, username,password,driverClassName这几个属性放到数据连接池对象中对应的属性。就是简单的set方法,我们看到这几个属性来自于DataSourceProperties这个类的对象,那么这个类的对象从哪里获得连接的基本属性呢,看下类的实现:

    @ConfigurationProperties(
        prefix = "spring.datasource"
    )
    public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
        private ClassLoader classLoader;
        private String name;
        private boolean generateUniqueName;
        private Class<? extends DataSource> type;
        private String driverClassName;
        private String url;
        private String username;
        private String password;
    

    类太长,我们看关键部分。

    这里还是用到了@ConfigurationProperties("spring.datasource")这个注解,它负责把properties中spring.datasource开头的属性装配到类DataSourceProperties对象中对应的属性中。然后再通过afterPropertiesSet方法放到DruidDataSourceWrapper中对应的属性。

    这样就会将所有的配置属性初始化到DataSourceBean中。

    这种配置Druid连接池方法中用到的最关键的技术就是Springboot的自动装配原理

    2.非Starter方法

    1. 引入依赖

      <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>druid</artifactId>
             <version>1.1.9</version>
      </dependency>
      
    2. 添加属性

      spring.datasource.druid.url=jdbc:mysql://localhost:3306/workflow?useUnicode=true&characterEncoding=utf-8&useSSL=false
      spring.datasource.druid.username=workflow
      spring.datasource.druid.password=workflow
      spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
      
      spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
      
      spring.datasource.druid.initial-size=1
      spring.datasource.druid.max-active=20
      spring.datasource.druid.min-idle=3
      spring.datasource.druid.max-wait=60000
      spring.datasource.druid.pool-prepared-statements=true
      spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
      spring.datasource.druid.filters=stat,wall,slf4j
      spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      
    3. 添加数据源配置类

      public class DataSourceConfig {
          @Bean
          @ConfigurationProperties(prefix = "spring.datasource.druid")
          public DataSource dataSource() {
              return new DruidDataSource();
          }
      }
      

      这里要注意配置properties文件中的url, username,password,driverClassName属性的写法,是包含“druid”的,因为这里也是用到了注解@ConfigurationProperties(prefix = "spring.datasource.druid")来自动装配属性的,我们指定了自动装配以spring.datasource.druid开头的属性,如果写成spring.datasource.url则是没有办法自动装配的,属性不会生效。

      当然还有其他方法就是不使用自动装配,通过注解@Value获取到配置文件属性,然后手动用set方法将属性设置到DataSource对象对应的属性中去,这样比较麻烦,不推荐。

    相关文章

      网友评论

          本文标题:springboot配置druid连接池

          本文链接:https://www.haomeiwen.com/subject/qeqvqhtx.html