热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

druid执行sql_Druid学习笔记(三)过滤器原理

在第一节的中我们说druid提供了监控的功能。那么这个监控的功能如何实现。首先我们要明确的是监控的本质就是通过代理模式对调用的方法进行统计。那么druid应该也是类似。但是我们在昨
在第一节的中我们说druid提供了监控的功能。那么这个监控的功能如何实现。首先我们要明确的是监控的本质就是通过代理模式对调用的方法进行统计。那么druid应该也是类似。但是我们在昨天的分析中说init()方法中有filter,这些filter又是做那些工作的。是否和监控有联系,这里先自己手写一个filter,据此来深入学习其原理和过程。1.定义过滤器,实现接口filtereventapter

@Componentpublic class MysqlLogFilter extends FilterEventAdapter { protected void statementExecuteUpdateBefore(StatementProxy statement, String sql) { } protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) { showLog(sql); } protected void statementExecuteQueryBefore(StatementProxy statement, String sql) { } protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) { showLog(sql); } protected void statementExecuteBefore(StatementProxy statement, String sql) { } protected void statementExecuteAfter(StatementProxy statement, String sql, boolean result) { showLog(sql); } public void showLog(String sql){ System.out.println("测试"+sql); }}执行效果e9e243b6b0d501ed79635646723b33bb.png首先考虑一下,这里如何分辨出这个bean要被durid使用,我们说spring中有接口beanpostprecessors,那么这里有没有使用,那么durid是如何识别的?通过一番查找,作者在druid的starter中找到了注入的方式。是采用list进行注入的。也就是说我们的filters其实在初始化的时候保存在dataseource中。daeeee7460ae173169dcafa4857f1d4b.png76289eed916d9dbbb3e209c8fa338686.png那么我们自定义的拦截器是如何执行的?我们还是根据sql的执行逻辑来看这个问题,首先是获取连接,然后通过连接得到statement,然后执行execute方法。那么我们从getconnection方法中查看。

public DruidPooledConnection getConnection(long maxWaitMillis) throws SQLException { init();//如果有过滤器 if (filters.size() > 0) {//初始化一个过滤器链 FilterChainImpl filterChain = new FilterChainImpl(this);//返回一个druidPooledConnction return filterChain.dataSource_connect(this, maxWaitMillis); } else { return getConnectionDirect(maxWaitMillis); } }//初始化 public FilterChainImpl(DataSourceProxy dataSource){ this.dataSource = dataSource; this.filterSize = getFilters().size(); }//从datasoruce中获取过滤器 public ListgetFilters() { return dataSource.getProxyFilters(); } @Override public DruidPooledConnection dataSource_connect(DruidDataSource dataSource, long maxWaitMillis) throws SQLException {//这里递归的对各种filterevent进行一些参数的设置。但是确实最后执行的。 if (this.pos 获取连接之后进行执行sql的时候,通过jdk动态代理执行。这里的statement就是getconnection获取的statement的封装。6dfc2cb2aa45e0c110352177879aedd4.png而这里封装返回来的statement就是这里的PreparedStatementProxyImpl。我们继续看一下里边的逻辑。1a116527bcd6ae7074544bc9a8c2a7a7.png最终会执行方法preparedStatement_execute

public boolean preparedStatement_execute(FilterChain chain, PreparedStatementProxy statement) throws SQLException { try {//执行一下处理的前置方法 this.statementExecuteBefore(statement, statement.getSql());//递归执行过滤器的方法 boolean firstResult = chain.preparedStatement_execute(statement);//执行结束之后的操作 this.statementExecuteAfter(statement, statement.getSql(), firstResult); return firstResult; } catch (SQLException var4) { this.statement_executeErrorAfter(statement, statement.getSql(), var4); throw var4; } catch (RuntimeException var5) { this.statement_executeErrorAfter(statement, statement.getSql(), var5); throw var5; } catch (Error var6) { this.statement_executeErrorAfter(statement, statement.getSql(), var6); throw var6; } }这里我们注意到druid的处理并没有采用mybatis插件那种机制,反而采用类似递归的方式,这个和springmvc的拦截器很类似。总结:durid通过注入数组的方式将druid拦截器注入到datasource中。在执行sql的时候先获取connection过程中采用递归的方式对该sql的执行的先前连接信息记录,并在获取连接之后封装成PreparedStatementProxyImpl,在进行jdk动态代理执行sql的时候,逐个递归的执行注入进来的拦截器FilterEventAdapter中的方法,从而完成sql的统计统计和监视功能。在查看代码的过程中,作者也发现druid其实也有对慢查询日志的监听功能。配置如下:

spring.datasource.druid.filter.stat.enabled=truespring.datasource.druid.filter.stat.log-slow-sql=truespring.datasource.druid.filter.stat.slow-sql-millis=1012b2b8af4187cf3edb8e766b5badaca4.png

6f9560f4fa7dcfa4ce8244d50215ee01.png




推荐阅读
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • mysql-cluster集群sql节点高可用keepalived的故障处理过程
    本文描述了mysql-cluster集群sql节点高可用keepalived的故障处理过程,包括故障发生时间、故障描述、故障分析等内容。根据keepalived的日志分析,发现bogus VRRP packet received on eth0 !!!等错误信息,进而导致vip地址失效,使得mysql-cluster的api无法访问。针对这个问题,本文提供了相应的解决方案。 ... [详细]
author-avatar
啦啦郭嘿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有