今天在做公司项目时,想要使用异步调用去处理方法。于是我把注解@Async 加到了自己一个方法上,后来发现并没有生效。
检查代码:
1.异步连接池
/**
- @Author wangping
- @Date 2021-10-28 10:37
- @Version 1.0
*/
//线程池
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.*;
@Configuration
@EnableAsync
public class SpringAsyncConfig {
@Bean("taskExecutor")
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(5);
// 设置最大线程数
executor.setMaxPoolSize(20);
//配置队列大小
executor.setQueueCapacity(Integer.MAX_VALUE);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("调用支付接口");
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
//执行初始化
executor.initialize();
return executor;
}
}2.@SpringBootApplication启动类当中已经添加@EnableAsync注解
3.目标类方法上已经添加@Async(“taskExecutor”)
可能应该是因为aop代理的缘故,被调用方法 和 调用处的代码都处在同一个类,所以只是相当于本类调用,并没有使用代理类 从而@Async并没有产生效果。
于是单独创建一个类调用@Async处理的方法,还是不行
@Async注解的实现都是基于Spring的AOP,后面创建的类也必须用spring管理
总结:
失效原因
1.@SpringBootApplication启动类当中没有添加@EnableAsync注解。
2.异步方法使用注解@Async的返回值只能为void或者Future。
3.没有走Spring的代理类。因为@Transactional和@Async注解的实现都是基于Spring的AOP,而AOP的实现是基于动态代理模式实现的。那么注解失效的原因就很明显了,有可能因为调用方法的是对象本身而不是代理对象,因为没有经过Spring容器管理。
解决方法:
这里具体说一下第三种情况的解决方法。
1.注解的方法必须是public方法。
2.方法一定要从另一个类中调用,也就是从类的外部调用,类的内部调用是无效的。
3.如果需要从类的内部调用,需要先获取其代理类。
创建spring转换类(转换的类一定是接口类)
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
-
@Author wangping
-
@Date 2021-10-11 16:21
-
@Version 1.0
*/
//整合Socket
@Component
public class SpringUtil implements ApplicationContextAware {private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}//通过class获取Bean.
public static T getBean(Class clazz){
return getApplicationContext().getBean(clazz);
}//通过name,以及Clazz返回指定的Bean
public static T getBean(String name,Class clazz){
return getApplicationContext().getBean(name, clazz);
}
}
创建接口类
public interface SocketService {
public void onlineAndnoplatePay(JSONObject json, OutputStream out);
}
实现类
import com.alibaba.fastjson.JSONObject;
import com.lianfu.smartparking.controller.ThreadServerSocket;
import com.lianfu.smartparking.netty.SocketController;
import com.lianfu.smartparking.service.SocketService;
import com.lianfu.smartparking.utils.AmountUtils;
import com.lianfu.smartparking.utils.SpringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.servlet.ServletContext;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
/**
- @Author wangping
- @Date 2021-11-11 14:12
- @Version 1.0
*/
@Service
public class SocketServiceImpl implements SocketService {
@Autowired
private ServletContext servletContext;
private final Logger logger = LoggerFactory.getLogger(ThreadServerSocket.class);
@Async("taskExecutor")
@Override
public void onlineAndnoplatePay(JSONObject json, OutputStream out) {
}
调用
private SocketService socketService=SpringUtil.getBean(SocketService.class);
socketService.onlineAndnoplatePay(json, out);