Summary of @Async usage in Spring

1. @controller controller (injection service)

2. @service service (inject dao)
3. @repository dao (implement dao access)
4. @component (instantiate ordinary pojo into spring container, equivalent to configuration file) @Component, @Service, @Controller
, @Repository annotated classes, and incorporate these classes into the spring container for management.
Write this below to introduce the scanning component of the component

The base-package is the package that needs to be scanned (including all sub-packages)
1. @Service is used to label business layer components
2, @Controller is used to label control layer components (such as actions in struts)
3, @Repository is used to label data Access components, that is, DAO components.
4. @Component generally refers to components. When components are not well classified, we can use this annotation to mark them.
@Service public class UserServiceImpl implements UserService { }
@Repository public class UserDaoImpl implements UserDao { } The default name of getBean is the class name (initial lowercase), if you want to customize it, you can specify it like @Service(" * "), this kind of The bean is a singleton by default. If you want to change it, you can use @Service("beanName")
@Scope("prototype") to change it. The initialization method and destruction method can be specified in the following way (the method name is arbitrary): @PostConstruct public void init() { }

1. Statement before use

@EnableAsync
@Component
@Lazy(false)
public class AsyncTask {
    private static final Logger logger = LoggerFactory.getLogger(AsyncTask.class);
    @Autowired
    private AutoAllocateCaseJob autoAllocateCaseJob;
    @Autowired
    private ColService colService;
    public AsyncTask(){
        logger.info("task初始化");
    }
    @Async
    public void startAllocateCaseJob(){
        autoAllocateCaseJob.execute();
    }
    @Async
    public Future<ReminderUserDetailRtnModel> queryCurrentPayables(UserDetailReq userDetailReq){
        AsyncResult<ReminderUserDetailRtnModel> result=null;
        try{
        ReminderUserDetailRtnModel reminderUserDetailRtn = colService.queryReminderUserDetail(userDetailReq);
            result=new AsyncResult<ReminderUserDetailRtnModel>(reminderUserDetailRtn);
        }catch(Exception e){
            logger.error("错误",e);
        }
        return result;
    }
}

@Lazy(false) loads immediately @Lazy(true) delays loading until it is used

2. Add it to the scan package in applicationContext.xml to ensure that it can be scanned

<context:component-scan base-package="com.vip.xfd.col.admin.async" />

3. Add annotations when used in related services

@Autowired
    private AsyncTask asyncTask; 

4. Use of @Configuration annotation

下面是一个典型的Spring配置文件(application-config.xml):
Xml代码 
[xml] view plain copy
<beans>  
        <bean id="orderService" class="com.acme.OrderService"/>  
                <constructor-arg ref="orderRepository"/>  
        </bean>  
        <bean id="orderRepository" class="com.acme.OrderRepository"/>  
                <constructor-arg ref="dataSource"/>  
        </bean>  
</beans>  

然后你就可以像这样来使用是bean了:

java代码

[java] view plain copy
ApplicationContext ctx = new ClassPathXmlApplicationContext("application-config.xml");  
OrderService orderService = (OrderService) ctx.getBean("orderService");  
现在Spring Java Configuration这个项目提供了一种通过java代码来装配bean的方案:

[java] view plain copy
@Configuration  
public class ApplicationConfig {  

        public @Bean OrderService orderService() {  
                return new OrderService(orderRepository());  
        }  

        public @Bean OrderRepository orderRepository() {  
                return new OrderRepository(dataSource());  
        }  

        public @Bean DataSource dataSource() {  
                // instantiate and return an new DataSource …  
        }  
}  
然后你就可以像这样来使用是bean了:

[java] view plain copy
JavaConfigApplicationContext ctx = new JavaConfigApplicationContext(ApplicationConfig.class);  
OrderService orderService = ctx.getBean(OrderService.class);

5. Introduction to @Async

In Spring, methods based on @Async annotation are called asynchronous methods; these methods will be executed in a separate thread when they are executed, and the caller can continue other operations without waiting for its completion.

 如何在Spring中启用@Async

基于Java配置的启用方式:
@Configuration  
@EnableAsync  
public class SpringAsyncConfig { ... }  
 基于XML配置文件的启用方式,配置如下:
<task:executor id="myexecutor" pool-size="5"  />  
<task:annotation-driven executor="myexecutor"/>  

These are the two ways of definition.
5.1. Calling with no return value based on @Async

示例如下:
@Async  //标注使用  
public void asyncMethodWithVoidReturnType() {  
    System.out.println("Execute method asynchronously. "  
      + Thread.currentThread().getName());  
}  

The way to use it is very simple, one callout can solve all problems.
5.2 Calls based on the return value of @Async

An example is as follows:

@Async  
public Future<String> asyncMethodWithReturnType() {  
    System.out.println("Execute method asynchronously - "  
      + Thread.currentThread().getName());  
    try {  
        Thread.sleep(5000);  
        return new AsyncResult<String>("hello world !!!!");  
    } catch (InterruptedException e) {  
        //  
    }  

    return null;  
}  

It can be found in the above example that the returned data type is Future type, which is an interface. The specific result type is AsyncResult, which is something to pay attention to.
Example of calling an asynchronous method that returns a result:

public void testAsyncAnnotationForMethodsWithReturnType()  
   throws InterruptedException, ExecutionException {  
    System.out.println("Invoking an asynchronous method. "  
      + Thread.currentThread().getName());  
    Future<String> future = asyncAnnotationExample.asyncMethodWithReturnType();  

    while (true) {  ///这里使用了循环判断,等待获取结果信息  
        if (future.isDone()) {  //判断是否执行完毕  
            System.out.println("Result from asynchronous process - " + future.get());  
            break;  
        }  
        System.out.println("Continue doing something else. ");  
        Thread.sleep(1000);  
    }  
}  

Analysis: These obtain the result information of the asynchronous method, which is realized by constantly checking the status of the Future to obtain whether the current asynchronous method has been executed.
5.3. Exception handling mechanism based on @Async call

在异步方法中,如果出现异常,对于调用者caller而言,是无法感知的。如果确实需要进行异常处理,则按照如下方法来进行处理:

1.  自定义实现AsyncTaskExecutor的任务执行器

     在这里定义处理具体异常的逻辑和方式。

2.  配置由自定义的TaskExecutor替代内置的任务执行器

示例步骤1,自定义的TaskExecutor
public class ExceptionHandlingAsyncTaskExecutor implements AsyncTaskExecutor {  
    private AsyncTaskExecutor executor;  
    public ExceptionHandlingAsyncTaskExecutor(AsyncTaskExecutor executor) {  
        this.executor = executor;  
     }  
      ////用独立的线程来包装,@Async其本质就是如此  
    public void execute(Runnable task) {       
      executor.execute(createWrappedRunnable(task));  
    }  
    public void execute(Runnable task, long startTimeout) {  
        /用独立的线程来包装,@Async其本质就是如此  
       executor.execute(createWrappedRunnable(task), startTimeout);           
    }   
    public Future submit(Runnable task) { return executor.submit(createWrappedRunnable(task));  
       //用独立的线程来包装,@Async其本质就是如此。  
    }   
    public Future submit(final Callable task) {  
      //用独立的线程来包装,@Async其本质就是如此。  
       return executor.submit(createCallable(task));   
    }   

    private Callable createCallable(final Callable task) {   
        return new Callable() {   
            public T call() throws Exception {   
                 try {   
                     return task.call();   
                 } catch (Exception ex) {   
                     handle(ex);   
                     throw ex;   
                   }   
                 }   
        };   
    }  

    private Runnable createWrappedRunnable(final Runnable task) {   
         return new Runnable() {   
             public void run() {   
                 try {  
                     task.run();   
                  } catch (Exception ex) {   
                     handle(ex);   
                   }   
            }  
        };   
    }   
    private void handle(Exception ex) {  
      //具体的异常逻辑处理的地方  
      System.err.println("Error during @Async execution: " + ex);  
    }  
}  

Analysis: It can be found that it implements AsyncTaskExecutor, and uses independent threads to execute specific method operations. In createCallable and createWrapperRunnable, the exception handling method and mechanism are defined.
handle() is where we need to focus on exception handling in the future.

  配置文件中的内容:
<task:annotation-driven executor="exceptionHandlingTaskExecutor" scheduler="defaultTaskScheduler" />  
<bean id="exceptionHandlingTaskExecutor" class="nl.jborsje.blog.examples.ExceptionHandlingAsyncTaskExecutor">  
    <constructor-arg ref="defaultTaskExecutor" />  
</bean>  
<task:executor id="defaultTaskExecutor" pool-size="5" />  
<task:scheduler id="defaultTaskScheduler" pool-size="1" />  

Analysis: The configuration here uses a custom taskExecutor to replace the default TaskExecutor.
5.4. Transaction processing mechanism in @Async calls

在@Async标注的方法,同时也适用了@Transactional进行了标注;在其调用数据库操作之时,将无法产生事务管理的控制,原因就在于其是基于异步处理的操作。

 那该如何给这些操作添加事务管理呢?可以将需要事务管理操作的方法放置到异步方法内部,在内部被调用的方法上添加@Transactional.

例如:  方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。

      方法B,使用了@Async来标注,  B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325721842&siteId=291194637