前言
在工作中会存在这种情况某些业务场景会对一份数据的属性进行多次设置,这种情况在传统的代码风格就是在一个方法中对应属性进行依次的set这种编码会在以后的业务迭代中造成很大的耦合,代码复用程度很低,后期维护成本会变大,这个时候就可以使用责任链模式对业务set这个步骤进行拆分做到可插拔式,从而做到减少迭代成本和维护成本对以后接手项目的同事友好
开始编写案例
我这里以电商项目中的商品属性设置为例productModel
1.开始搭建一个spring boot 项目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring-batch</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.创建对应案例数据
package com.wym.pojo;
import lombok.Data;
@Data
public class ProductModel {
private Integer id;
private String productCode;
private String productName;
private String productTitle;
private String productTag;
private String productRegion;
private Integer stockNumber;
private String brandName;
}
package com.wym.pojo;
import lombok.Data;
@Data
public class ProductParamModel {
private String vendorCode;
}
3.创建责任链处理器
创建一个处理接口,子类根据自己的业务特色去实现接口,对数据进行加工
public interface ProductPostProcessor {
void productDataProcess(List<? extends ProductModel> productModelList, ProductParamModel productParamModel);
}
这里我设置3个常用的商品处理
@Component
@Slf4j
@Order(1) //为了后期方便业务操作顺序编排
public class ProductBrandMappingPostProcessor implements ProductPostProcessor {
@Override
public void productDataProcess(List<? extends ProductModel> productModelList, ProductParamModel productParamModel) {
log.error("进入商品品牌设置");
}
}
@Component
@Slf4j
@Order(2)
public class ProductCodeMappingPostProcessor implements ProductPostProcessor {
@Override
public void productDataProcess(List<? extends ProductModel> productModelList, ProductParamModel productParamModel) {
log.error("进入商品映射设置");
}
}
@Slf4j
@Component
@Order(3)
public class ProductStockNumberPostProcessor implements ProductPostProcessor {
@Override
public void productDataProcess(List<? extends ProductModel> productModelList, ProductParamModel productParamModel) {
log.error("进入商品库存设置");
}
}
这个时候就已经创建好了责任链处理器,接下来就是开始业务调用
4.创建mvc调用
controller
@RequestMapping("/test")
@Slf4j
@RestController
public class ProductController {
@Autowired
private ProductServer productServer;
@GetMapping("/query")
public String queryProduct() {
productServer.queryProduct();
return "成功";
}
}
server
public interface ProductServer {
public List<ProductModel> queryProduct();
}
impl 这里就是核心点如何操作这个责任链 ApplicationListener 这个取获取容器中的处理器,并排序
@Service
@Slf4j
public class ProductServerImpl implements ProductServer, ApplicationListener<ContextRefreshedEvent> {
private static List<ProductPostProcessor> productPostProcessorList;
private List<ProductPostProcessor> getProductPostProcesser(ContextRefreshedEvent contextRefreshedEvent) {
//子容器加载完毕不进这个逻辑
if (contextRefreshedEvent.getApplicationContext().getParent() == null) {
//监听容器加载完毕
Map<String, ProductPostProcessor> beansOfType = contextRefreshedEvent.getApplicationContext().getBeansOfType(ProductPostProcessor.class);
log.error("商品后置处理器注入");
List<ProductPostProcessor> postProcessList = new ArrayList<>(beansOfType.values());
postProcessList.sort((a, b) -> {
Order aOrder = AnnotationUtils.findAnnotation(a.getClass(), Order.class);
Order bOrder = AnnotationUtils.findAnnotation(b.getClass(), Order.class);
if (aOrder == null && bOrder == null) {
return 0;
}
if (aOrder == null) {
return 1;
}
if (bOrder == null) {
return -1;
}
return aOrder.value() - bOrder.value();
}
);
return postProcessList;
}
return null;
}
@Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
List<ProductPostProcessor> postProcessor = getProductPostProcesser(contextRefreshedEvent);
if (!CollectionUtils.isEmpty(postProcessor))
{ productPostProcessorList = postProcessor; }
}
@Override public List<ProductModel> queryProduct()
{ ProductModel productModel = new ProductModel(); productModel.setId(0);
productModel.setProductCode("");
productModel.setProductName("");
productModel.setProductTitle("");
productModel.setProductTag("");
productModel.setProductRegion("");
productModel.setStockNumber(0);
productModel.setBrandName("");
ProductParamModel productParamModel = new ProductParamModel(); productParamModel.setVendorCode("1231");
productPostProcessorList.forEach(item -> item.productDataProcess(Arrays.asList(productModel), productParamModel)); return null; }
}
进行验证
调用 http://localhost:8080/test/query 就会在控制台中打印出
2023-01-09 11:07:42.178 ERROR 25096 --- [nio-8080-exec-2] c.w.p.i.ProductBrandMappingPostProcessor : 进入商品品牌设置
2023-01-09 11:07:42.178 ERROR 25096 --- [nio-8080-exec-2] c.w.p.i.ProductCodeMappingPostProcessor : 进入商品映射设置
2023-01-09 11:07:42.179 ERROR 25096 --- [nio-8080-exec-2] c.w.p.i.ProductStockNumberPostProcessor : 进入商品库存设置
这样就做到了业务分离对后期的维护有帮助
到此这篇关于Spring责任链模式使用实例讲解的文章就介绍到这了,更多相关Spring责任链模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!