Spring利用InitializingBean定义基于业务队列处理Handler
Posted boonya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring利用InitializingBean定义基于业务队列处理Handler相关的知识,希望对你有一定的参考价值。
目录
利用Spring InitializingBean自动注入Handler
在各种高效的编程框架中都有Handler身影,将一类业务通过Handler统一输出可以简化业务编程。比如:业务编号、业务持久化处理、业务异常等处理。
定义Handler类
public interface ServiceHandler {
ServiceType type();
void execute(String data);
void handleException(String data);
}
定义类似面向过程编程的需求处理
项目结构:
面向过程服务:
接口:
/**
* 面向过程的用户密码修改服务
*/
public interface UserPwdUpdateService extends ServiceHandler {
}
实现:
@Service
public class UserPwdUpdateServiceImpl implements UserPwdUpdateService {
@Override
public ServiceType type() {
return ServiceType.USER_PWD_UPDATE;
}
@Override
public void execute(String data) {
// 1.反序列化数据进行操作
// 2.执行用户密码持久化操作
}
@Override
public void handleException(String data) {
// 1.反序列化数据进行操作
// 2.用户密码相关数据回滚
}
}
上面是一个很面向过程的处理方式!!!
泛型与面向对象的设计
Handler接口泛型:
/**
* 业务处理泛型
* @param <T>
*/
public interface ServiceHandler<T> {
ServiceType type();
void execute(T data);
void handleException(T data);
}
泛型接口定义:
/**
* 用户密码修改服务
*/
public interface UserPwdUpdateService extends ServiceHandler<User> {
}
业务接口实现:
@Service
public class UserPwdUpdateServiceImpl implements UserPwdUpdateService {
@Override
public ServiceType type() {
return ServiceType.USER_PWD_UPDATE;
}
@Override
public void execute(User user) {
// 执行用户密码持久化操作
}
@Override
public void handleException(User user) {
// 用户密码相关数据回滚
}
}
利用Spring InitializingBean自动注入Handler
@Component
public class ServiceTaskManger extends Thread implements InitializingBean {
public static Map<ServiceType, ServiceHandler> handlers = new ConcurrentHashMap<>();
@Autowired
private Map<String, ServiceHandler<?>> handlerMap;
@Override
public void afterPropertiesSet() throws Exception {
Preconditions.checkNotNull(handlerMap, "Handler 未初始化");
for (ServiceHandler handler : handlerMap.values()) {
handlers.put(handler.type(), handler);
}
}
@Override
public void run() {
}
}
业务处理统一放入队列执行
定义队列数据对象:
/**
* 数据类型
* @param <T>
*/
@Data
public class AbstractService<T> {
ServiceType type;
T data;
}
管理队列任务:
/**
* 业务处理任务管理器
*/
@Component
public class ServiceTaskManger extends Thread implements InitializingBean {
public static Queue<AbstractService> queue = new LinkedBlockingDeque<>();
private static Map<ServiceType, ServiceHandler> handlers = new ConcurrentHashMap<>();
@Autowired
private Map<String, ServiceHandler<?>> handlerMap;
// 任务窃取线程池
private ExecutorService executorService = Executors.newWorkStealingPool();
@Override
public void afterPropertiesSet() throws Exception {
Preconditions.checkNotNull(handlerMap, "Handler 未初始化");
for (ServiceHandler handler : handlerMap.values()) {
handlers.put(handler.type(), handler);
}
}
@Override
public void run() {
while (true){
int count = queue.size();
// 处理任务条件:队列不为空
if(count>0){
executorService.submit(new Runnable() {
@Override
public void run() {
for (int i = 0; i < count; i++) {
AbstractService service = queue.poll();
ServiceHandler serviceHandler = handlers.get( service.getType());
try{
serviceHandler.execute(service.getData());
}catch (Exception e){
serviceHandler.handleException(service.getData());
}
}
}
});
}
}
}
}
任务管理API接口
@RestController
@RequestMapping("/services")
public class ServiceTaskController {
@RequestMapping("/account/save")
public String accountSaveMoney(Account account){
AccountService accountService = new AccountService();
accountService.setType(ServiceType.ACCOUNT_SAVE_MONEY);
accountService.setData(account);
ServiceTaskManger.queue.add(accountService);
return "success";
}
@RequestMapping("/account/withdraw")
public String accountWithdrawMoney(Account account){
AccountService accountService = new AccountService();
accountService.setType(ServiceType.ACCOUNT_WITHDRAW_MONEY);
accountService.setData(account);
ServiceTaskManger.queue.add(accountService);
return "success";
}
}
队列交互的接口适合跨系统异步业务。
以上是关于Spring利用InitializingBean定义基于业务队列处理Handler的主要内容,如果未能解决你的问题,请参考以下文章
spring 中 InitializingBean 接口使用理解
spring常用接口 InitializingBean的作用