Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring AOP proxy doesn't work as expected

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 IllegalArgumentExceptions 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;
}
like image 327
baymon Avatar asked Mar 16 '15 20:03

baymon


1 Answers

@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 {
    ...
}
like image 59
Rohit Jain Avatar answered Nov 16 '22 04:11

Rohit Jain