我是小懒猴,人狠话不多,直接上才艺。
上次编写完抽象类方式的模板设计模式,这次采用自定义注解配合注解式方式进行完成模板设计模式。
开始将编写前,先要捋顺思路,如何使用注解方式模板设计模式,不能想到什么开始写什么,不然容易一头雾水。
主要分以下部分:
- enum枚举
- 自定义注解
- 接口类
- 实现子类
- Service管理器
- 任务执行器
- controller
第一步—Enum
@Getter
@AllArgsConstructor
public enum YwEnum {
ONE(10000,"OneService","OneService运行"),
TWO(20000,"TwoService","TwoService运行"),
;
public Integer num;
public String code;
public String msg;
public static final HashMap<String , YwEnum> CACHE_MAP = new HashMap<>();
static {
for (YwEnum value : values()) {
CACHE_MAP.put(value.code,value);
}
}
public YwEnum get(String code) {
return CACHE_MAP.get(code);
}
}
enum的三个参数
1.num 用来排序要执行的service,
2.code 用来保存需要执行的service类名称
3.msg 用来描述service的作用
第二步—自定义注解
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface YwAnno {
String value() default "";
YwEnum type();
}
用来定义需要执行的子类
第三步—执行接口类
/**
*询价规则处理器 - 规则处理器接口
*/
public interface YwHandler {
/**
* 执行规则
*
* @return true-通过 false-未通过
*/
boolean handle(Req context);
}
接口是实现子类进行实现用的,后续管理器会使用到该接口名称,进行获取该实现子类的所有类。
第四步—实现子类
@Slf4j
@Service
@YwAnno(type = YwEnum.ONE)
public class OneService implements YwHandler {
@Override
public boolean handle(Req context) {
System.out.println("OneService执行了------------");
return true;
}
}
@Slf4j
@Service
@YwAnno(type = YwEnum.TWO)
public class TwoService implements YwHandler {
@Override
public boolean handle(Req context) {
System.out.println("TwoService执行了-----");
return true;
}
}
实现子类主要有两点需要关注
1.实现的接口
2.自定义注解来确定自己的执行文件
第五步—Service初始化管理器
@Slf4j
@Component
public class YwManager implements ApplicationContextAware {
public static final HashMap<YwEnum,YwHandler> CACHE_MAP = new HashMap<>();
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, YwHandler> beans = applicationContext.getBeansOfType(YwHandler.class);
if (MapUtil.isEmpty(beans)) {
return;
}
for (YwHandler bean : beans.values()) {
YwAnno annotation = bean.getClass().getAnnotation(YwAnno.class);
if (ObjectUtil.isNull(annotation)) {
continue;
}
CACHE_MAP.put(annotation.type(),bean);
log.debug("初始化主规则处理器 {}-{}", annotation.type().code, annotation.type().msg);
}
}
public static Map<YwEnum,YwHandler> getBeanMap() {
return CACHE_MAP;
}
public static YwHandler getBean(YwEnum ywEnum) {
return CACHE_MAP.get(ywEnum);
}
}
Service初始化管理器,主要是为了获取实现接口类的所有子类进行缓存起来,让执行器调用的时候可以之间获取到所有。
第六步—执行器
/**
* 执行器
*/
@Slf4j
@Component
public class YwExecute {
public static HashMap<YwEnum,YwHandler> CACHE_MAP;
public static boolean execute(Req req) {
if (MapUtil.isEmpty(CACHE_MAP)) {
CACHE_MAP = YwManager.getBeanMap().entrySet().stream()
.sorted(Comparator.comparing(e -> e.getKey().num))
.collect(LinkedHashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue()), Map::putAll);
}
//循环执行规则 - 规则组中的规则处理器
for (Map.Entry<YwEnum, YwHandler> ywEnumYwHandlerEntry : CACHE_MAP.entrySet()) {
YwEnum key = ywEnumYwHandlerEntry.getKey();
YwHandler value = ywEnumYwHandlerEntry.getValue();
boolean isPassed = value.handle(req);
log.debug("执行 {}-{} 结果==> {}", key.num, key.msg, isPassed);
if (!isPassed) {
log.debug("询价流程结束");
return false;
}
}
return true;
}
}
执行器获取管理器中缓存起来的service服务,按照num进行排序,最后进行循环遍历一个一个进行service的执行。
第七步—Controller
@RestController
@RequestMapping("/yw")
public class YwController {
@RequestMapping("/select")
public RespT select(Req reqT) {
if (YwExecute.execute(reqT)) {
System.out.println("select成功");
}
return null;
}
}
最后一步没什么可说的。此时已经完成了注解式完成模板设计模式。
总结
注解式模板设计模式
执行器通过执行管理器所管理的所有service进行遍历进行达到业务模板的拆分。
重要组件分为:
- 枚举
- 自定义注解
- 自定义接口
- 子类
- service管理器
- 任务执行器
从上到下依次创建。