How do spring @ async methods add annotations to implement asynchronous calls

This article mainly introduces how to add annotations to spring @ async method to realize asynchronous call. The example code is introduced in great detail, which has certain reference value for everyone's study or work. Friends in need can refer to it

In the process of using spring framework, we often use @ async annotation to execute some methods asynchronously to improve the execution efficiency of the system. Today, let's discuss how spring accomplishes this function.

When scanning beans, spring will scan whether the method contains @ async annotation. If so, spring will dynamically generate a subclass for the bean, which is called 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 enter the proxy class. If 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. It puts the methods to be executed into the queue and waits for the thread pool to read the queue to complete the execution of the methods, thus completing the asynchronous function.

We can notice that when we reconfigure the task, there are parameters that let us configure the number of thread pools. Because of this implementation method, adding @ async annotation to method calls in the same class is invalid!, The reason is that when you are in the same class, the method call is executed in the class body, and spring cannot intercept this method call.

In a further step, spring provides us with AOP, aspect oriented functions. Its principle is similar to that of asynchronous annotation. When spring starts the container, it will scan the classes defined by the aspect. When these classes are injected, what is injected is also a proxy class. When you call these methods, it is essentially the calling proxy class. By executing the method corresponding to the parent class through the proxy class, spring only needs to execute a piece of code before and after the call to complete the implementation of AOP!

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

Brief introduction:

Spring schedules tasks with @ r_ 403_ 2271 @ execution provides annotation support. By setting the @ async annotation on the method, the method can be called asynchronously. That is, the caller will return immediately when calling, and the actual execution of the called method is handed over to spring's taskexecutor.

Open @ async annotation:

<task:annotation-driven executor="annotationExecutor" />
<!-- 支持 @Async 注解 -->
<task:executor id="annotationExecutor" pool-size="20"/>

At the same time, add < context: component scan / > scan annotation.

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

@Component
public class TestAsyncBean {
  public void sayHello4() throws InterruptedException {
    Thread.sleep(2 * 1000);//网络连接中 。。。消息发送中。。。
    System.out.println("我爱你啊!");
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
  @Test
  public void test_sayHello4() throws InterruptedException,ExecutionException {
    System.out.println("你不爱我了么?");
    testAsyncBean.sayHello4();
    System.out.println("回的这么慢,你肯定不爱我了,我们还是分手吧。。。");
    Thread.sleep(3 * 1000);// 不让主进程过早结束
  }
}

Output results:

你不爱我了么?
我爱你啊!
回的这么慢,我们还是分手吧。。。 

Synchronous calls will proceed in code order. If there is a need to wait, it will be blocked there and will not continue downward.

Asynchronous calls using @ async:

@Component
public class TestAsyncBean {
  @Async
  public void sayHello3() throws InterruptedException {
    Thread.sleep(2 * 1000);//网络连接中 。。。消息发送中。。。
    System.out.println("我爱你啊!");
  }
}
@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("你不爱我了么?");
    testAsyncBean.sayHello3();
    System.out.println("你竟无话可说,我们分手吧。。。");
    Thread.sleep(3 * 1000);// 不让主进程过早结束
  }
}

Output results:

你不爱我了么?
你竟无话可说,我们分手吧。。。
我爱你啊!

Asynchronous call, which executes the called method by opening a new thread, and does not affect the main thread@ R_ 403_ 2271 @ the actual execution is left to spring's task executor.

There is no return value in the above method. Here is an asynchronous call with a return value:

@Component
public class TestAsyncBean {
  @Async
  public String sayHello2() throws InterruptedException {
    Thread.sleep(2 * 1000);//网络连接中 。。。消息发送中。。。
    return "我爱你啊!";// 调用方调用后会立即返回,所以返回null
  }
}
@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("你不爱我了么?");
    System.out.println(testAsyncBean.sayHello2());
    System.out.println("你说的啥? 我们还是分手吧。。。");
    Thread.sleep(3 * 1000);// 不让主进程过早结束
  }
}

Output results:

你不爱我了么?
null
你说的啥? 我们还是分手吧。。。

It is not possible to obtain the return value directly. Here you need to use asynchronous callback, @ R_ 403_ 2271 @ the return value must be future < >, just like callable and future.

Next, get the return value of asynchronous call through asyncresult < >

@Component
public class TestAsyncBean {
  @Async
  public Future<String> sayHello1() throws InterruptedException {
    int thinking = 2;
    Thread.sleep(thinking * 1000);//网络连接中 。。。消息发送中。。。
    System.out.println("我爱你啊!");
    return new AsyncResult<String>("发送消息用了"+thinking+"秒");
  }
}
@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("你不爱我了么?");
    future = testAsyncBean.sayHello1();
    System.out.println("你竟无话可说,我们分手吧。。。");
    Thread.sleep(3 * 1000);// 不让主进程过早结束
    System.out.println(future.get());
  }
}

Output results:

你不爱我了么?
你竟无话可说,我们分手吧。。。
我爱你啊!

It took 2 seconds to send the message

The above is the whole content of this article. I hope it will help you in your study, and I hope you will support us a lot.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>