A method annotated with Spring’s @Async, @Cacheable or @Transactional annotations will not work as expected
if invoked directly from within its class.
This is because Spring generates a proxy class with wrapper code to manage the method’s asynchronicity (@Async), to cache methods
invocations (@Cacheable), or to handle the transaction (@Transactional). However, when called using this, the
proxy instance is bypassed, and the method is invoked directly without the required wrapper code.
Replace calls to @Async, @Cacheable or @Transactional methods via this with calls on an
instance that was injected by Spring (@Autowired, @Resource or @Inject). The injected instance is a proxy on
which the methods can be invoked safely.
@Service
public class AsyncNotificationProcessor implements NotificationProcessor {
@Override
public void process(Notification notification) {
processAsync(notification); // Noncompliant, call bypasses proxy
retrieveNotification(notification.id); // Noncompliant, call bypasses proxy and will not be cached
}
@Async
public processAsync(Notification notification) {
// ...
}
@Cacheable
public Notification retrieveNotification(Long id) {
// ...
}
}
@Service
public class AsyncNotificationProcessor implements NotificationProcessor {
@Resource
private AsyncNotificationProcessor asyncNotificationProcessor;
@Override
public void process(Notification notification) {
asyncNotificationProcessor.processAsync(notification); // Compliant, call via injected proxy
asyncNotificationProcessor.retrieveNotification(notification.id); // Compliant, the call will be cached
}
@Async
public processAsync(Notification notification) {
// ...
}
@Cacheable
public Notification retrieveNotification(Long id) {
// ...
}
}