如何拦截实例由我自己创建的 JdbcTemplate



我想做的是在任何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
}
}

它非常适合JdbcTemplateNamedParameterJdbcTemplate@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 调用 .

因此,我的问题是">如何拦截我自己创造的JdbcTemplateNamedParameterJdbcTemplate
任何意见和建议将不胜感激。谢谢!

更新
我还调查了不同的方法,如 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);
}
}

这样,您可以通过将JdbcTemplatebean 放入ApplicationContext中,在@Aspect中拦截它时使 Spring 能够用 AOP 代理它。您现在可以通过以下方式自动连线它:

@Autowired private JdbcTemplate jdbcTemplate;

最新更新