Java 如何拦截自己创建实例的JdbcTemplate
我要做的是在为当前会话执行的任何DQL(“选择…”)或DML(插入/更新/删除…)之后收集DB统计值。Java 如何拦截自己创建实例的JdbcTemplate,java,spring,spring-boot,aop,jdbctemplate,Java,Spring,Spring Boot,Aop,Jdbctemplate,我要做的是在为当前会话执行的任何DQL(“选择…”)或DML(插入/更新/删除…)之后收集DB统计值。 目前,我已利用Spring AOP实现以下目标: @Aspect @Component public class StatisticalValueCollector { @After("execution(* org.springframework.jdbc.core..*JdbcOperations.*(String, ..))") public void collectSt
目前,我已利用Spring AOP实现以下目标:
@Aspect
@Component
public class StatisticalValueCollector {
@After("execution(* org.springframework.jdbc.core..*JdbcOperations.*(String, ..))")
public void collectStatisTicalValues(JoinPoint jp) {
//Collect DB statistical values
}
}
它对@Autowired
注释的JdbcTemplate
和NamedParameterJdbcTemplate
都非常有效,但是当我创建它们的实例时ㄋ 就我个人而言,它不起作用
工作示例:
@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 ...");
@Autowired
jdbc模板jdbc模板;
...
列表结果=jdbcTemplate.queryForList(“选择…”);
未工作示例:
@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 ...");
DriverManager数据源ds=new DriverManager数据源();
...
JdbcTemplate JdbcTemplate=新的JdbcTemplate(ds);
列表结果=jdbcTemplate.queryForList(“选择…”);
据我所知,如果JdbcTemplate
是由Spring创建的,那么它可以根据本文进行代理
因此,我的问题是“如何拦截我自己创建的JdbcTemplate
或NamedParameterJdbcTemplate
”如有任何意见和建议,将不胜感激。谢谢 更新
我还调查了不同的方法,如和,似乎唯一的解决方案是使用纯AspectJ或其他什么?在用
@Configuration
注释的类中,将JdbcTemplate
定义为@Bean
:
@Configuration
public class JdbcConfiguration {
private DriverManagerDatasource ds = new DriverManagerDatasource();
@Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(ds);
}
}
这样,通过将JdbcTemplate
bean放入ApplicationContext
中,可以使Spring在拦截@Aspect
时使用AOP代理它。现在,您可以使用以下工具自动关联:
@Autowired private JdbcTemplate jdbcTemplate;
如果在这两种情况下都像这样打印JDBC模板实例
System.out.println(jdbcTemplate+“\n”+jdbcTemplate.getClass());
然后,对于你自己创造的,你会看到
org.springframework.jdbc.core。JdbcTemplate@3c71cf3e
类org.springframework.jdbc.core.jdbc模板
而对于自动注入式,您将看到
org.springframework.jdbc.core。JdbcTemplate@8f39224
类org.springframework.jdbc.core.JdbcTemplate$$EnhancerBySpringCGLIB$$59a5407f
找出区别了吗?对于后者,如果存在针对它的方面,Spring将创建一个动态代理。只有当存在一个动态代理时,SpringAOP才能注册它的方面建议
我不是Spring用户,所以我不知道是否有另一种创建JDBC模板的规范方法,可以根据需要自动为其创建动态代理。因此,除非您想手动创建代理(这是可能的,但不必要地复杂)或找到其他方法,否则只需使用依赖注入(DI)和自动连接。这不是使用Spring的最初目的吗?对于像Spring这样的DI容器来说,创建可以注入的依赖项是一种反模式
如果您坚持使用非正统且难以测试的方法(如何为调用构造函数的局部变量注入模拟?),则始终可以使用完整AspectJ作为Spring AOP的替代方案。但是我怀疑在这种情况下它是否值得。当然,但问题是如何将AOP与未自动连接的JDBC模板结合使用。不能将AOP用于使用
新建
创建的实例。我刚刚给了你一种截取JdbcTemplate
方法的方法,让它成为Spring管理的@Bean
@kriagaex,你可能在错误的答案下发布了它。谢谢你的回复!我知道我不能用Spring AOP代理Spring创建的对象。所以我会考虑你的建议。你好。你问了一个问题,我回答了。所以,请检查我的答案,然后接受+upvote,如果你认为它是正确的(我当然会)。