开发者社区 问答 正文

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

我想要做的是在对当前会话执行的任何DQL(“ SELECT ...”)或DML(INSERT / UPDATE / DELETE ...)之后收集DB统计值。 当前,我已经利用Spring AOP实现了以下目标:

@Aspect @Component public class StatisticalValueCollector { @After("execution(* org.springframework.jdbc.core..JdbcOperations.(String, ..))") public void collectStatisTicalValues(JoinPoint jp) { //Collect DB statistical values } } 它的工作原理perfectlly两者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创建? ”; 任何意见和建议将不胜感激。谢谢!

展开
收起
被纵养的懒猫 2019-10-08 17:20:47 1391 分享 版权
阿里云 AI 助理回答

要解决您遇到的问题,即在自行创建JdbcTemplateNamedParameterJdbcTemplate实例时也能应用Spring AOP进行拦截,您可以考虑以下几种方法:

1. 使用Spring Bean工厂方法

一个直接的解决方案是通过Spring的Bean工厂方法来创建这些实例,这样它们就会被Spring管理并自动代理。例如:

@Configuration
public class AppConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
        return new NamedParameterJdbcTemplate(dataSource);
    }
}

然后在您的服务类中,通过@Autowired注入这些Bean,这样AOP切面就能正常工作了。

2. Spring ProxyFactoryBean

如果您有特殊需求必须手动创建实例,可以使用Spring的ProxyFactoryBean来手动创建代理对象,这样即使手动实例化,也能应用AOP逻辑。

@Bean
public ProxyFactoryBean jdbcTemplateProxy() {
    ProxyFactoryBean factory = new ProxyFactoryBean();
    factory.setTarget(new JdbcTemplate(dataSource));
    factory.addAdvice(new StatisticalValueInterceptor()); // 自定义拦截器实现统计收集
    factory.setInterfaces(JdbcTemplate.class);
    return factory;
}

// 类似地为NamedParameterJdbcTemplate创建代理

这里,您需要实现一个自定义拦截器(如StatisticalValueInterceptor),它应该扩展自MethodInterceptor接口,并在其中实现统计值收集的逻辑。

3. 手动编织(Weaving)

如果上述方案不适用,且您确实需要在运行时动态地对非Spring管理的对象应用切面,那么可能需要探索更底层的手动编织技术。这通常涉及到使用AspectJ的load-time weaving (LTW) 或 compile-time weaving (CTW),但这会增加复杂度,并可能引入额外的依赖和配置。

结论

最推荐的方法是尽量让Spring容器管理所有需要被AOP切面影响的Bean,如方法1所示。这不仅简化了配置,也保持了代码的清晰和一致性。只有在特定场景下,才考虑采用更复杂的方案,如手动编织或使用ProxyFactoryBean

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
问答分类:
问答地址: