Actually I'am confused about the behavior of spring proxies. I think I know the main difference between the proxy mechanisms of j2ee, cglib and aspectj. I have the aspectj auto proxy enabled in my configuration class and aspectj is included in the class path.
My configuration
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ApplicationConfiguration {
...
}
AspectJ dependency
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.5</version>
</dependency>
By using this simple setup I've assumed that the bean injection work as intended. But instead my application results in IllegalArgumentException
s with messages like "Can not set [...] field [...] to com.sun.proxy.$Proxy30". That means spring uses the j2ee proxy for my service, even with aspectj proxy enabled.
Finally i've figured out that the interfaces on my service causes this behavior. It seems that spring decides to use the j2ee proxy when my service implements any interface. If I remove them, it works.
Failure:
@Service
@Validated
public class MyService implements Interface1, Interface2 {
@override
public void methodFromInterface1() {
}
@override
public void methodFromInterface2() {
}
public void serviceMethod() {
}
}
OK:
@Service
@Validated
public class MyService {
public void methodFromInterface1() {
}
public void methodFromInterface2() {
}
public void serviceMethod() {
}
}
Until now I've understand that interfaces are required for the j2ee proxy. But it's new for me, that a cglib/aspectj proxy doesn't work with beans that implements interfaces.
Is there a way to...
... force spring to not use j2ee proxies?
... force spring to use cglib/aspectj proxies (even for classes that have interfaces)?
Is that a bug or desired behavior of spring?
Edit: Example updated, @Transational
replaced by @Validated
Edit2: Solution: @Validated
is affected by the MethodValidationPostProcessor
. So the property proxyTargetClass
has to be set to true
for this bean.
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
final MethodValidationPostProcessor methodValidationPostProcessor;
methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setProxyTargetClass(true);
return methodValidationPostProcessor;
}
@EnableAspectJAutoProxy
annotation applies to @Aspect
annotations, not on @Transactional
annotations. For that, you need to have @EnableTransactionManagement
annotation on @Configuration
class, with proxyTargetClass = true
attribute value.
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableTransactionManagement(proxyTargetClass = true)
public class ApplicationConfiguration {
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With