druid
1.概述
因为druid会用到springboot的自动装配,对这个有基础的可以略过第3个直接进入主题
ps(错误和不足的地方欢迎大佬指正)
2.环境配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.17.RELEASE</version>
</parent>
// web 依赖 基于web环境
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
// 使用JdbcTemplate 操作访问
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
// druid 依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.14</version>
</dependency>
// mysql驱动包
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
// application.yml 配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username:
password:
druid:
stat-view-servlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow: 127.0.0.1
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: admin
login-password: 123456
web-stat-filter:
enabled: true
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
3.springboot 自动装配浅析
@EnableAutoConfiguration注解
第一步:点进去老铁,不要怕,奥里给!
发现其中里面有一个开启自动配置的注解,继续点进去
好了,点到为止,@Import注解直接导入了一个ImportSelector的实现类,此时肯定有人会问,这个ImportSelector又是什么鬼捏,先声明一下,这个ImportSelector是spring的扩展点之一,铁子们继续往下看
这里是springboot启动之后会执行ConfigurationClassPostProcessor后置处理器的postProcessBeanDefinitionRegistry方法,因为它实现了BeanDefinitionRegistryPostProcessor接口,在spring声明周期里会执行,现在先不管什么时候执行的,后面有时间再写一个spring的,然后往下一步一步走,就到了解析import注解的地方,仔细瞅着铁子们,找到selectImports 方法
如果自定义的实现了DeferredImportSelector 表示推迟选中,会放入group里面依次取出然后再将执行selector.selectImports(metadata)返回的全限定名称作为配置类依次扫描加载注册
这个时候铁子们肯定会问,看这个搞什么鬼,别急别急,铁子们精彩继续!
回到AutoConfigurationImportSelector 找到selectImports方法进入getAutoConfigurationEntry
继续getCandidateConfigurations
终于快结束了,看到没有spring会默认加载class目录下面的META-INF/spring.factories文件的配置类
好,铁子们激动不激动,现在找到druid的starter这个配置文件 发现里面有一个正是我们要找的DruidDataSourceAutoConfigure,我想这个时候大家应该能自己手写一个springboot的starter了吧,嘻嘻
4. DruidDataSourceAutoConfigure
下面对这个类上的注解依次解析
4.1 @Configuration
这个注解不要问 直接过
4.2 @ConditionalOnClass(DruidDataSource.class)
这个表示是否存在DruidDataSource类 存在才会加载DruidDataSourceAutoConfigure配置类,这里肯定存在啦
4.3 @AutoConfigureBefore
@AutoConfigureBefore表示在DataSourceAutoConfiguration类之前加载DruidDataSourceAutoConfigure配置类,为什么捏,大家可以在springboot的autoconfigure的META-INF/spring.factories里面找到EnableAutoConfiguration下的JdbcTemplateAutoConfiguration和DataSourceAutoConfiguration,这两个类是spring默认加载装配的一个类,JdbcTemplateAutoConfiguration里面有一个@AutoConfigureAfter(DataSourceAutoConfiguration.class),
这个AutoConfigureAfter表示JdbcTemplateAutoConfiguration要在DataSourceAutoConfiguration类后面再加载,这样就造成一个加载的顺序:
DruidDataSourceAutoConfigure->DataSourceAutoConfiguration->JdbcTemplateAutoConfiguration,
此时细心的同学肯定会发现,在JdbcTemplateAutoConfiguration类上有一@ConditionalOnSingleCandidate(DataSource.class)注解,这个注解表示只要存在一个主的DataSource,此类才会被加载,因为JdbcTemplate需要数据源,什么是主的DataSource呢?
就是如果已经注入了一个DataSource或者注入了一个加了@Primary注解的DataSource,那么JdbcTemplateAutoConfiguration就会被加载,那为什么DruidDataSourceAutoConfigure要在DataSourceAutoConfiguration之前进行加载呢,聪明的铁子们肯定想到啦,我们来到DataSourceAutoConfiguration类里面看到
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) 表示如果存在数据源就不会被加载,相应Import里面默认的连接池就不会被spring加载,这样就避免了数据源的冲突,这个时候可能就会有人问了,不是可以配置多数据源吗?对的,可以,这个只是springboot将自己的数据源关闭掉,并不会影响你自定义的
4.4 @EnableConfigurationProperties
DruidStatProperties 和监控有关
DataSourceProperties:数据源的属性配置(spring.datasource)
4.5 @Import
同样和监控有关
@Import({DruidSpringAopConfiguration.class,
DruidStatViewServletConfiguration.class,
DruidWebStatFilterConfiguration.class,
DruidFilterConfiguration.class})
监控的东西可以在配置文件开启,使用
5.DataSourceBean
DruidDataSourceWrapper:使用Wrapper对数据源进行了包装,并且在创建Bean之后执行了init方法,先进入DruidDataSourceWrapper
@ConfigurationProperties(“spring.datasource.druid”):注入了druid的配置并且实现了spring的InitializingBean的afterPropertiesSet方法,
也就是说在bean的生命周期执行过程中执行了afterPropertiesSet 此时private DataSourceProperties basicProperties;这个已经被注入,
super.setUsername(basicProperties.determineUsername());表示你如果没有spring.datasource.druid.username而配置了spring.datasource.username
那么就会读取spring.datasource.username的属性值,至于init方法去它的父类肯定能找到,至此,DruidDataSource 创建完成
我们再来看一下JdbcTemplateAutoConfiguration,通过JdbcTemplateConfiguration创建了JdbcTemplate
,DataSource被JdbcTemplate所持有,而NamedParameterJdbcOperations持有JdbcTemplate,在JdbcTemplate进行了扩展,支持命名参数特性
小明收尾~耗子尾汁