java - 如何拦截自己创建实例的JdbcTemplate
问题描述
我想要做的是在为当前会话执行的任何DQL(“SELECT ...”)或DML (INSERT/UPDATE/DELETE ...)之后收集数据库统计值。
目前,我利用Spring AOP来实现这一点,如下所示:
@Aspect
@Component
public class StatisticalValueCollector {
@After("execution(* org.springframework.jdbc.core..*JdbcOperations.*(String, ..))")
public void collectStatisTicalValues(JoinPoint jp) {
//Collect DB statistical values
}
}
它适用于两者JdbcTemplate
并由NamedParameterJdbcTemplate
注释@Autowired
,但是当我自己创建它们的实例ㄋ时,它不起作用。
工作示例:
@Autowired
JdbcTemplate jdbcTemplate;
...
List<Map<String, Object>> result = jdbcTemplate.queryForList("SELECT ...");
不工作的例子:
DriverManagerDatasource ds = new DriverManagerDatasource();
...
JdbcTemplate jdbcTemplate = new JdbcTemplate (ds);
List<Map<String, Object>> result = jdbcTemplate.queryForList("SELECT ...");
据我所知,似乎如果JdbcTemplate
是由 Spring 创建的,则可以根据这篇文章进行代理 - AOP: Able to Intercept JDBCTemplate calls but not NamedParameterJdbcTemplate calls
。
因此,我的问题是“如何拦截JdbcTemplate
或NamedParameterJdbcTemplate
自己创建? ”;
任何意见和建议将不胜感激。谢谢!
更新
我还调查了p6spy和datasource-proxy等不同的方法,似乎唯一的解决方案是使用纯AspectJ或其他方法?
解决方案
如果在这两种情况下,您都像这样打印 JDBC 模板实例
System.out.println(jdbcTemplate + "\n " + jdbcTemplate.getClass());
然后对于您自己创建的那个,您将看到
org.springframework.jdbc.core.JdbcTemplate@3c71cf3e
class org.springframework.jdbc.core.JdbcTemplate
而对于自动注入的,您会看到
org.springframework.jdbc.core.JdbcTemplate@8f39224
class org.springframework.jdbc.core.JdbcTemplate$$EnhancerBySpringCGLIB$$59a5407f
指出不同?对于后者,如果存在针对它的方面,则 Spring 创建一个动态代理。只有当有一个动态代理时,Spring AOP 才有东西可以注册它的方面建议。
我不是 Spring 用户,所以我不知道是否有另一种规范的方式来创建 JDBC 模板,根据需要自动为其创建动态代理。因此,除非您想手动创建代理(这是可能的但不必要的复杂)或找到另一种方法来执行此操作,否则只需使用依赖注入 (DI) 和自动连接。这不是首先使用 Spring 的全部意义吗?创建可以注入的依赖项对于像 Spring 这样的 DI 容器来说是一种反模式。
如果您坚持使用非正统且难以测试(如何为调用构造函数的局部变量注入模拟?)方法,则始终可以使用完整的 AspectJ 作为 Spring AOP 的替代方案。但我怀疑在这种情况下是否值得。
推荐阅读
- java - 可分页属性大小值不生效
- apache-flink - 在路线图上发展 TTL?
- c# - DateTime.TryParseExact 的结果有 DateTimeKind.Unspecified 尽管输入的日期时间字符串包含时区信息
- python-3.x - 是否可以使用 Drive API 获取完整的文档修订历史记录?
- docker - 使用 Jenkins 容器构建 Dockerfile 并部署 Flask 应用
- javascript - 对对象的数字数组进行排序
- node.js - 如何让 Strapi 使 Mongo / Mongoose 索引成为“id”列?
- java - Android - 警报对话框出现瞬间而不是变黑
- javascript - 使用 Mongoose 创建一个在 NodeJS 中过期的实体
- git - Git - 获取 repo 克隆地址