Druid源码分析(六)-- 获取连接
Druid源码分析(六)-- 获取连接
获取连接,执行sql
运行 druid-spring-boot-starter 模块的 com.alibaba.druid.spring.boot.demo.DemoApplication
在 DruidDataSource#getConnection() 打上断点
然后通过postman调用接口
可以看到,走进程序断点了,userDao.findOne 通过hibernate 去获取连接
// UserServiceImpl.java
public User findById(Long id) {
return userDao.findOne(id);
}
获取连接的时候,会再去调一次init 函数,因为之前已经初始化过了,所以会直接return。这就是前几篇文章分析的双重校验+锁起作用的地方,避免了重复初始化。
if (inited) {
return;
}
然后会根据是否有filter ,执行不通的逻辑,如果没有filter ,就直接获取连接,有的话,会通过责任链的模式执行函数。
我们这里是有监控filter ,所以走的是责任链的模式,和init 的时候类似,最后他还是调用getConnectionDirect()
所以,我们接着看这个函数
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
int notFullTimeoutRetryCnt = 0;
// 这里用了一个死循环
for (;;) {
// handle notFullTimeoutRetry
DruidPooledConnection poolableConnection;
try {
poolableConnection = getConnectionInternal(maxWaitMillis);
...
接着往下看getConnectionInternal
private DruidPooledConnection getConnectionInternal(long maxWait) throws SQLException {
if (closed) {
// 如果数据源关闭了就抛异常
connectErrorCountUpdater.incrementAndGet(this);
throw new DataSourceClosedException("dataSource already closed at " + new Date(closeTimeMillis));
}
...
// 这里有行代码,这个写法第一次见
for (boolean createDirect = false;;) {
// 编译后是这样的
while(true) {
...
// 最后返回的是DruidPooledConnection ,把DruidConnectionHolder又包装了一层
DruidPooledConnection poolalbeConnection = new DruidPooledConnection(holder);
最后获取完连接,会执行sql,下面是Hibernate 生成的sql
Hibernate: select user0_.id as id1_0_0_, user0_.name as name2_0_0_ from user user0_ where user0_.id=?