introduction
Spring Boot is a popular Java development framework that provides rich functions and convenient configurations, allowing developers to focus more on business logic. In terms of asynchronous programming, Spring Boot provides @Async annotation, which allows methods to be executed asynchronously and improves the concurrency performance of the system. However, there are some potential pitfalls to be paid attention to when using @Async annotation. This article will explore the 8 major pit points that may be encountered when using @Async annotation in Spring Boot and provide corresponding solutions.
1. Missing @EnableAsync annotation
In use@Async
Before annotation, you must add it on the main configuration class of the Spring Boot application@EnableAsync
Annotation to enable support for asynchronous methods. If this step is ignored,@Async
The annotation will not take effect.
@SpringBootApplication @EnableAsync public class YourApplication { public static void main(String[] args) { (, args); } }
2. Asynchronous methods need to be independent
quilt@Async
Annotation modified methods cannot be called directly by other methods in the same class. Because Spring will generate a proxy class at runtime, when calling an asynchronous method, it actually calls the method of this proxy class. Therefore, if the asynchronous method is called directly in the same class,@Async
The annotation will not take effect.
@Service public class YourService { @Async public void asyncMethod() { // Logic of asynchronous execution } public void callingAsyncMethod() { // Directly calling asyncMethod will not be executed asynchronously asyncMethod(); } }
The solution is through injectionYourService
the proxy object to call the asynchronous method.
@Service public class YourService { @Autowired private YourService self; @Async public void asyncMethod() { // Logic of asynchronous execution } public void callingAsyncMethod() { // Call asynchronous method through proxy object (); } }
3. Different asynchronous methods cannot be called each other
In the same class, if one asynchronous method calls another asynchronous method, there will also be a problem that it will not execute asynchronously. This is because Spring uses proxy-based AOP to implement asynchronous methods by default, and method calls inside the proxy object will not trigger AOP interception.
@Service public class YourService { @Async public void asyncMethod1() { // Logic of asynchronous execution } @Async public void asyncMethod2() { // Logic of asynchronous execution asyncMethod1(); // The call here will not be executed asynchronously } }
The solution is to get the current proxy object through() and then call the asynchronous method.
@Service public class YourService { @Autowired private YourService self; @Async public void asyncMethod1() { // Logic of asynchronous execution } @Async public void asyncMethod2() { // Logic of asynchronous execution self.asyncMethod1(); // Asynchronous execution through proxy object call } }
4. The asynchronous method with the return value void cannot catch the exception
If using@Async
The return value of the asynchronous method of the annotation isvoid
, then the exception thrown in this method will not be caught. This is because exceptions cannot be passed between the calling thread of the asynchronous method and the thread that actually executes the asynchronous method.
@Service public class YourService { @Async public void asyncMethod() { // Logic of asynchronous execution throw new RuntimeException("Async method exception"); } }
The solution is to set the return value toFuture
, so that you can call itget()
Exception was caught during method.
@Service public class YourService { @Async public Future<Void> asyncMethod() { // Logic of asynchronous execution throw new RuntimeException("Async method exception"); } }
When calling an asynchronous method, you can useFuture
ofget()
The method catches the exception.
@Service public class YourService { @Autowired private YourService self; public void callAsyncMethod() { try { ().get(); } catch (Exception e) { //Catch exception } } }
5. The method with @Async annotation cannot be called directly from the outside
If called directly in the same class with@Async
The annotation method cannot be executed asynchronously. Because Spring will generate a proxy class at runtime, external direct calls are actually called methods of the original class, not methods of the proxy class.
@Service public class YourService { @Async public void asyncMethod() { // Logic of asynchronous execution } } @Service public class AnotherService { @Autowired private YourService yourService; public void callAsyncMethod() { // Directly calling asyncMethod from outside will not be executed asynchronously (); } }
The solution is through injectionYourService
the proxy object to call the asynchronous method.
@Service public class YourService { @Autowired private YourService self; @Async public void asyncMethod() { // Logic of asynchronous execution } } @Service public class AnotherService { @Autowired private YourService self; public void callAsyncMethod() { // Call asynchronous method through proxy object (); } }
6. @Async method does not work with private method
@Async
Annotations are only valid for public methods, so `private
The method cannot be executed asynchronously. If you try to give one
privateMethod Add
@Async` annotation will not produce any effect.
@Service public class YourService { @Async private void asyncMethod() { // The @Async annotation here will not take effect } }
The solution is to extract the logic to be executed asynchronously into a public method and call this public method in the private method.
@Service public class YourService { @Async public void asyncMethod() { doAsyncMethod(); } private void doAsyncMethod() { // Logic of asynchronous execution } }
7. Missing asynchronous thread pool configuration
When using @Async annotation, Spring Boot creates a thread pool to execute asynchronous methods by default. If not configured, the default is SimpleAsyncTaskExecutor, which is a single-threaded executor that may cause performance bottlenecks.
To solve this problem, a suitable thread pool can be configured. Here is an example configuration:
@Configuration @EnableAsync public class AsyncConfig extends AsyncConfigurerSupport { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); (5); (10); (25); ("Async-"); (); return executor; } }
This configuration is usedThreadPoolTaskExecutor
, and set parameters such as the number of core threads, maximum number of threads, queue capacity, etc., and adjust them according to actual conditions.
8. Compatibility between asynchronous methods and transactions
By default, use@Async
The annotation method is incompatible with transactions. Because invoking the method using the transaction@Async
When annotated methods, transactions will not be propagated into the asynchronous method, and the asynchronous method will be executed without transactions.
The solution is to@Async
Annotations are added to methods of another class, and asynchronous methods are called through proxy objects.
@Service public class YourService { @Autowired private AsyncService asyncService; @Transactional public void transactionalMethod() { // Call asynchronous method in transaction (); } } @Service public class AsyncService { @Async public void asyncMethod() { // Logic of asynchronous execution } }
By moving the asynchronous method into another class, you can ensure that the asynchronous method is executed in a new transaction and does not conflict with external transactions.
Conclusion
use@Async
Annotations can improve the concurrency performance of the system, but some potential problems need to be paid attention to when using them. Learn more about Spring Boot@Async
These 8 major pit points annotated and corresponding solutions can better apply asynchronous programming to ensure the reliability and performance of the system. Hope this article helps you understand and use asynchronous annotations in Spring Boot.
The above is a detailed content of the pit points encountered and solutions encountered by @Async annotation in SpringBoot. For more information about SpringBoot @Async pit points, please follow my other related articles!