相关疑难解决方法(0)

如果Spring可以成功拦截@Configuration类中的内部类函数调用,为什么它在常规bean中不支持它?

我最近注意到,Spring成功拦截了@Configuration类中的内部类函数调用,但没有拦截常规的bean。

这样的电话

@Repository
public class CustomerDAO {  
    @Transactional(value=TxType.REQUIRED)
    public void saveCustomer() {
        // some DB stuff here...
        saveCustomer2();
    }
    @Transactional(value=TxType.REQUIRES_NEW)
    public void saveCustomer2() {
        // more DB stuff here
    }
}
Run Code Online (Sandbox Code Playgroud)

未能启动新事务,因为尽管在CustomerDAO代理中执行了saveCustomer()的代码,但在已解包的CustomerDAO类中执行了saveCustomer2()的代码,正如我在调试器中查看“ this”所看到的,等等Spring没有机会拦截对saveCustomer2的调用。

但是,在以下示例中,当transactionManager()调用createDataSource()时,它将被正确拦截并调用代理的createDataSource(),而不是未包装类的调用,而在调试器中查看“ this”可以证明这一点。

@Configuration
public class PersistenceJPAConfig {
    @Bean
    public DriverManagerDataSource createDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        //dataSource.set ... DB stuff here
        return dataSource;
    }

   @Bean 
       public PlatformTransactionManager transactionManager(   ){
           DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(createDataSource());
           return transactionManager;
       }
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,为什么在第二个示例中Spring可以正确地拦截内部类函数调用,而在第一个示例中则不能。是否使用不同类型的动态代理?

编辑: 从这里的答案和其他来源,我现在了解以下内容:@Transactional是使用Spring AOP实现的,其中代理模式通过包装/组合用户类来执行。AOP代理足够通用,因此许多方面都可以链接在一起,并且可以是CGLib代理或Java动态代理。

在@Configuration类中,Spring还使用CGLib创建一个从用户@Configuration类继承的增强类,并在调用用户的/ super函数之前用做一些额外工作的函数覆盖用户的@Bean函数,例如检查是否是否是该函数的首次调用。该课程是代理吗?这取决于定义。您可能会说这是一个使用真实对象继承的代理,而不是使用组合包装。

总而言之,从这里给出的答案中,我了解到这是两种完全不同的机制。为什么做出这些设计选择是另一个悬而未决的问题。

java proxy spring interception

21
推荐指数
2
解决办法
445
查看次数

标签 统计

interception ×1

java ×1

proxy ×1

spring ×1