Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
438 views
in Technique[技术] by (71.8m points)

java - Spring @Async ignored

I am having troubles invoking a method asynchronously in Spring, when the invoker is an embedded library receiving notifications from an external system. The code looks as below:

@Service
public class DefaultNotificationProcessor implements NotificationProcessor {

    private NotificationClient client;


    @Override
    public void process(Notification notification) {
        processAsync(notification);
    }

    @PostConstruct
    public void startClient() {
        client = new NotificationClient(this, clientPort);
        client.start(); 
    }

    @PreDestroy
    public void stopClient() {
        client.stop();
    }

    @Async
    private void processAsync(Notification notification) {
        // Heavy processing
    }
}

The NotificationClient internally has a thread in which it receives notifications from another system. It accepts a NotificationProcessor in its constructor which is basically the object that will do the actual processing of notifications.

In the above code, I have given the Spring bean as the processor and attempted to process the notification asynchronously by using @Async annotation. However, it appears the notification is processed in the same thread as the one used by NotificationClient. Effectively, @Async is ignored.

What am I missing here?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

@Async (as well as @Transactional and other similar annotations) will not work when the method is invoked via this (on when @Async is used for private methods*), as long as you do not use real AspectJ compiletime or runtime weaving.

*the private method thing is: when the method is private, then it must been invoked via this - so this is more the consequence then the cause

So change your code:

@Service
public class DefaultNotificationProcessor implements NotificationProcessor {


    @Resource
    private DefaultNotificationProcessor selfReference;


    @Override
    public void process(Notification notification) {
        selfReference.processAsync(notification);
    }


    //the method must not been private
    //the method must been invoked via a bean reference
    @Async
    void processAsync(Notification notification) {
        // Heavy processing
    }
}

See also the answers for: Does Spring @Transactional attribute work on a private method? -- this is the same problem


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...