实际上,我对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注入按预期工作。但是,我的应用程序却出现了"IllegalArgumentException"异常,消息显示为“无法将[...]字段[...]设置为com.sun.proxy.$Proxy30”。这意味着Spring在我的服务中使用J2EE代理,即使启用了AspectJ代理。
最后,我发现我的服务上的接口导致了这种行为。似乎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代理需要接口。但是对于实现接口的bean而言,cglib/aspectj代理对我来说是新的概念。
是否有一种方法...
... 强制Spring不使用j2ee代理?
... 强制Spring使用cglib/aspectj代理(即使对于具有接口的类)?
这是Spring的一个bug还是期望的行为?
编辑:示例已更新,@Transactional被@Validated替换。
编辑2:解决方案:@Validated受MethodValidationPostProcessor影响。因此,此bean的proxyTargetClass属性必须设置为true。
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
final MethodValidationPostProcessor methodValidationPostProcessor;
methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setProxyTargetClass(true);
return methodValidationPostProcessor;
}
proxyTargetClass = true
,使Spring对于带有@Transactional
注解的类使用CGLib代理。 - Rohit Jain@EnableAspectJAutoProxy
注解。要在事务上启用aspectj代理,可以使用@EnableTransactionManagement
注解的mode
属性。 - Rohit Jain