我想做的是在任何DQL("选择..."(或DML(插入/更新/删除...(之后收集数据库统计值这是为当前会话执行的。
目前,我已经利用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:能够拦截 JDBCTemplate 调用,但不能拦截 NamedParameterJdbcTemplate 调用 .
因此,我的问题是">如何拦截我自己创造的JdbcTemplate
或NamedParameterJdbcTemplate
?
任何意见和建议将不胜感激。谢谢!
更新
我还调查了不同的方法,如 p6spy 和数据源代理,似乎唯一的解决方案是使用纯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的替代品。但我怀疑在这种情况下是否值得。
在用@Configuration
注释的类中,将JdbcTemplate
定义为@Bean
:
@Configuration
public class JdbcConfiguration {
private DriverManagerDatasource ds = new DriverManagerDatasource();
@Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(ds);
}
}
这样,您可以通过将JdbcTemplate
bean 放入ApplicationContext
中,在@Aspect
中拦截它时使 Spring 能够用 AOP 代理它。您现在可以通过以下方式自动连线它:
@Autowired private JdbcTemplate jdbcTemplate;