【问题标题】:Spring AOP proxy doesn't work as expectedSpring AOP 代理无法按预期工作
【发布时间】:2015-05-19 02:34:35
【问题描述】:

实际上,我对 spring 代理的行为感到困惑。我想我知道 j2ee、cglib 和 aspectj 的代理机制之间的主要区别。我在我的配置类中启用了 aspectj 自动代理,并且 aspectj 包含在类路径中。

我的配置

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ApplicationConfiguration {
    ...
}

AspectJ 依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.5</version>
</dependency>

通过使用这个简单的设置,我假设 bean 注入按预期工作。但相反,我的应用程序导致 IllegalArgumentExceptions 出现“无法将 [...] 字段 [...] 设置为 com.sun.proxy.$Proxy30”之类的消息。这意味着即使启用了 aspectj 代理,spring 也会为我的服务使用 j2ee 代理。

最后我发现我的服务上的接口导致了这种行为。当我的服务实现任何接口时,spring 似乎决定使用 j2ee 代理。如果我删除它们,它会起作用。

失败:

@Service
@Validated
public class MyService implements Interface1, Interface2 {

    @override
    public void methodFromInterface1() {
    }

    @override
    public void methodFromInterface2() {
    }

    public void serviceMethod() {
    }
}

好的:

@Service
@Validated
public class MyService {

    public void methodFromInterface1() {
    }

    public void methodFromInterface2() {
    }

    public void serviceMethod() {
    }
}

到目前为止,我已经了解 j2ee 代理需要接口。但这对我来说是新的,cglib/aspectj 代理不适用于实现接口的 bean。

有没有办法...

...强制 spring 不使用 j2ee 代理?

...强制 spring 使用 cglib/aspectj 代理(即使对于具有接口的类)?

这是弹簧的错误还是期望的行为?

编辑:示例已更新,@Transational 替换为 @Validated

Edit2:解决方案@ValidatedMethodValidationPostProcessor 影响。所以这个 bean 的属性 proxyTargetClass 必须设置为 true

@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
    final MethodValidationPostProcessor methodValidationPostProcessor;
    methodValidationPostProcessor = new MethodValidationPostProcessor();
    methodValidationPostProcessor.setProxyTargetClass(true);
    return methodValidationPostProcessor;
}

【问题讨论】:

    标签: java spring dependency-injection proxy aspectj


    【解决方案1】:

    @EnableAspectJAutoProxy 注释适用于@Aspect 注释,不适用于@Transactional 注释。为此,您需要在 @Configuration 类上添加 @EnableTransactionManagement 注释,并带有 proxyTargetClass = true 属性值。

    @Configuration
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    @EnableTransactionManagement(proxyTargetClass = true)
    public class ApplicationConfiguration {
        ...
    }
    

    【讨论】:

    • 你是对的。我还在第二个配置类上配置了 @EnableTransactionManagement,但没有 proxyTargetClass = true,并且由于某种原因它可以工作。请注意,这只是一个示例,可以通过服务类上的 @Validated 重现问题。
    • @baymon 没错。因此,您必须将 proxyTargetClass = true 设置为该注释,以让 spring 为 @Transactional 注释类使用 CGLib 代理。
    • @baymon 事实上,如果你不使用 Spring AOP,你甚至不需要@EnableAspectJAutoProxy 注解。要在事务上启用 aspectj 代理,您可以使用 @EnableTransactionManagement 注释的 mode 属性。
    • 我通过比较我的两个项目来分析描述的行为。我当前的项目不使用数据库,但我想使用基于代理的 bean 验证...我已经修改了我的示例以停止关注 @Transactional :) ...我的问题发生在在我的服务类上使用 @Validated 。很抱歉造成混乱!
    猜你喜欢
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 2022-10-21
    • 1970-01-01
    • 1970-01-01
    • 2019-06-26
    • 2019-01-05
    • 1970-01-01
    相关资源
    最近更新 更多