业务场景:在一个业务系统中,订单提交后并计算该笔订单的手续费。
为了下单这个逻辑的完整性和代码执行更高效,我们可以把“下单”和“计算手续费”拆分成两个不同的业务逻辑。
一、定义一个发布事件的工具类EventUtils
这个工具类只负责发布事件
public class EventUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public static void publishEvent(final ApplicationEvent event) {
if (TransactionSynchronizationManager.isActualTransactionActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
applicationContext.publishEvent(event);
super.afterCommit();
}
});
} else {
applicationContext.publishEvent(event);
}
}
}
二、定义一个事件模型
就是创建一个普通java类并继承org.springframework.context.ApplicationEvent,它主要负责数据传输
public class OrderSubmitEvent extends ApplicationEvent{
private static final long serialVersionUID = -726198855342137539L;
public OrderSubmitEvent(Object source) {
super(source);
}
}
三、 定义一个订单服务类
@Service
public class OrderService {
static final Logger logger = LoggerFactory.getLogger(OrderService.class);
// 创建订单方法 ps:这只是测试代码,如果写正式代码建议定义接口
public void create(){
logger.info("OrderService.create");
// 执行创建订单逻辑
// do something...
// 要传输的信息,这里可以是object类型,我为了演示就直接传一个字符串过去
String message = "订单提交成功了!";
// 发布事件
EventUtils.publishEvent(new OrderSubmitEvent(message));
logger.info("OrderService.publishEvent");
}
}
四、写监听器
既然订单创建好了并发布了事件,那我们就需要监听这个“订单已提交”的事件,去执行自己的逻辑,这个监听器需要实现 org.springframework.context.ApplicationListener 然后重写它的方法。
@Component
public class OrderSubmitListener implements ApplicationListener<OrderSubmitEvent>{
final static Logger logger = LoggerFactory.getLogger(OrderSubmitListener.class);
@Async
@Override
public void onApplicationEvent(OrderSubmitEvent orderCompleteEvent) {
Object source = orderCompleteEvent.getSource();
logger.info("OrderSubmitListener onApplicationEvent source:[{}]", ToStringBuilder.reflectionToString(source));
}
}
五、配置文件
直接贴代码,如果直接复制下面配置,需要修改一下你们的包路径
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<!-- 扫描远程服务类注解 !!!记得自己改包名!!!-->
<context:component-scan base-package="com.xxx.**.**" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component" />
</context:component-scan>
<!-- 方便在非spring管理环境中获取bean !!!记得自己改包名-->
<bean id="eventUtils" class="com.xxx.util.EventUtils"/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
六、测试
@RestController
@RequestMapping(value = "api/test",produces = "text/plain;charset=UTF-8")
public class TestController {
static final Logger logger = LoggerFactory.getLogger(TestController.class);
@Autowired
private Configuration configuration;
@Autowired
private OrderService orderService;
@RequestMapping(value = "/index")
public String order(){
logger.info("TestController create order run");
orderService.create();
return "index";
}
}
控制台结果:
17:10:53.936 [qtp1899280551-20] INFO com.xxx.web.controller.TestController - TestController create order run
17:10:53.937 [qtp1899280551-20] INFO com.xxx.springevent.OrderService - OrderService.create
17:10:53.947 [qtp1899280551-20] INFO com.xxx.springevent.OrderSubmitListener - OrderSubmitListener onApplicationEvent source:[java.lang.String@73bd9107[value={订,单,提,交,成,功,了,!},hash=171729329]]
17:10:53.947 [qtp1899280551-20] INFO com.xxx.springevent.OrderService - OrderService.publishEvent
本文介绍了如何使用Spring的事件驱动机制将订单创建与手续费计算逻辑解耦。通过创建一个发布事件的工具类EventUtils,定义事件模型OrderSubmitEvent,订单服务类OrderService来发布事件,以及编写监听器OrderSubmitListener来处理事件,实现了业务流程的异步处理。测试结果显示,订单创建后立即返回,手续费计算在事务提交后异步执行。
1万+

被折叠的 条评论
为什么被折叠?



