How to add annotation to spring @ async method to realize asynchronous call

Time:2020-6-24

This article mainly introduces how to add annotation to spring @ async method to realize asynchronous call. The example code is introduced in detail in this article, which has certain reference value for your study or work. You can refer to

In the process of using spring framework, we will use @ async annotation to execute some methods asynchronously in many times to improve the execution efficiency of the system. Today we’re going to talk about how spring does this.

When spring scans a bean, it will scan whether the method contains @ async annotation. If it does, spring will dynamically generate a subclass for the bean, which we call the proxy class (?), The proxy class inherits the bean we wrote, and then injects the proxy class. At this time, when executing this method, it will go to the proxy class. When the proxy class judges that this method needs to be executed asynchronously, it will not call the corresponding method of the parent class (the bean we originally wrote). Spring maintains a queue by itself. It puts the methods to be executed into the queue and waits for the thread pool to read the queue and complete the execution of the methods, thus completing the asynchronous function.

We can pay attention to the number of thread pools that we need to configure when we reconfigure tasks. Because of this implementation method, it is invalid to add @ async annotation to method calls in the same class! , because when you are in the same class, the method call is executed in the class body, and spring cannot intercept the method call.

In that step, spring provides us with AOP, aspect oriented functions. Its principle is similar to that of asynchronous annotation. When spring starts the container, it scans the classes defined by the facet. When these classes are injected, they are also injected with proxy classes. When you call these methods, they are essentially called proxy classes. Through the proxy class to execute the method corresponding to the parent class, spring only needs to execute some code before and after the call to complete the AOP implementation!

Finally, we have another question: how does spring dynamically generate subclasses of a class? Agent class?

Brief introduction:

Spring provides annotation support for task scheduling and asynchronous method execution. By setting @ async annotation on the method, the method can be called asynchronously. That is to say, the caller will return immediately at the time of the call, and the actual execution of the called method is to be completed by spring’s taskexecutor.

Open @ async annotation:

<task:annotation-driven executor="annotationExecutor" />
<! -- support @ async annotation -- >
<task:executor pool-size="20"/>

Join at the same time< context:component-scan / >Scan comments.

For comparison, let’s start with a synchronous call:

@Component
public class TestAsyncBean {
  public void sayHello4() throws InterruptedException {
    Thread.sleep (2 * 1000); // network connection... Message sending...
    System.out.println ("I love you!");
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
  @Test
  public void test_sayHello4() throws InterruptedException, ExecutionException {
    System.out.println ("don't you love me?");
    testAsyncBean.sayHello4();
    System.out.println ("it's so slow to return. You must not love me. Let's break up..."... "";
    Thread.sleep (3 * 1000); // do not let the main process end prematurely
  }
}

Output results:

Don't you love me?
I love you!
You must not love me. Let's break up...

The synchronous call will go on in code order. If there is a need to wait, it will block there and no longer go down.

Asynchronous call using @ async:

@Component
public class TestAsyncBean {
  @Async
  public void sayHello3() throws InterruptedException {
    Thread.sleep (2 * 1000); // network connection... Message sending...
    System.out.println ("I love you!");
  }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
  @Autowired
  private TestAsyncBean testAsyncBean;
  @Test
  public void test_sayHello3() throws InterruptedException, ExecutionException {
    System.out.println ("don't you love me?");
    testAsyncBean.sayHello3();
    System.out.println ("you have nothing to say. Let's break up... "";
    Thread.sleep (3 * 1000); // do not let the main process end prematurely
  }
}

Output results:

Don't you love me?
You have nothing to say. Let's break up...
I love you!

Asynchronous call, which executes the call method by opening a new thread, does not affect the main thread. The actual execution of the asynchronous method is left to spring’s taskexecutor.

There is no return value in the above method. The asynchronous call with return value is attempted as follows:

@Component
public class TestAsyncBean {
  @Async
  public String sayHello2() throws InterruptedException {
    Thread.sleep (2 * 1000); // network connection... Message sending...
    Return "I love you!"; // the caller will return immediately after calling, so null is returned
  }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
  @Autowired
  private TestAsyncBean testAsyncBean;
  @Test
  public void test_sayHello2() throws InterruptedException, ExecutionException {
    System.out.println ("don't you love me?");
    System.out.println(testAsyncBean.sayHello2());
    System.out.println ("what did you say? Let's break up..."... "";
    Thread.sleep (3 * 1000); // do not let the main process end prematurely
  }
}

Output results:

Don't you love me?
null
What are you talking about? Let's break up...

It’s not possible to get the return value directly. Asynchronous callback is needed here. The return value of asynchronous method must be future < > like callable and future.

The following uses asyncresult < > to get the return value of the asynchronous call:

@Component
public class TestAsyncBean {
  @Async
  public Future<String> sayHello1() throws InterruptedException {
    int thinking = 2;
    Thread.sleep (thinking * 1000); // network connection... Message sending...
    System.out.println ("I love you!");
    Return new asyncresult < string >;
  }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
  @Autowired
  private TestAsyncBean testAsyncBean;
  @Test
  public void test_sayHello1() throws InterruptedException, ExecutionException {
    Future<String> future = null;
    System.out.println ("don't you love me?");
    future = testAsyncBean.sayHello1();
    System.out.println ("you have nothing to say. Let's break up... "";
    Thread.sleep (3 * 1000); // do not let the main process end prematurely
    System.out.println(future.get());
  }
}

Output results:

Don't you love me?
You have nothing to say. Let's break up...
I love you!

It took two seconds to send a message

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.