1、自定义注解
@Retention
@Target(ElementType.TYPE)
@Document
public @interface RegisterExecutor {
//定义执行类型
String value();
}
该注解用来定义不同执行类型service实现类
2、bean工厂
项目启动后,扫描1中@RegisterExecutor标注的bean,获取bean放入容器中
public class ExecutorFactory implements ApplicationListener<ApplicationReadyEvent> {
//存放bean的容器
private final static Map<String,IExecutorService> EXECUTOR_MAP = new ConcurrentHashMap<>();
@Override
public void onApplicationEvent(ApplicationReadyEvent application) {
//获取被注解RegisterExecutor 标注的bean
ConfigurableApplicationContext applicationContext = application.getApplicationContext();
Map<String,Object> beans = applicationContext .getBeansWithAnnotation(RegisterExecutor .class);
beans.values.forEach(bean->{
RegisterExecutor annotation = bean.getClass().getAnnotation(RegisterExecutor.class);
EXECUTOR_MAP.put(annotation.value(),(IExecutorService)bean);
});
}
}
3、service执行类
/**
*定义执行类需要做的事情
*这里不使用接口也行,直接在2中工厂装载bean时强转父类,在4中直接调用抽象类模板方法executor()也是一样的
*/
public interface IExecutorService {
void executor(Object obj);
}
//利用抽象类,定义执行模板
public abstract class AbstractExecutorServiceImpl implements IExecutorService {
@Override
public void executor(Object obj){
//这里弱需要传递一些参数给下面执行类可使用ThreadLocal传参,可在这里构建上下文信息,在TypeAServiceImpl 获取使用
doExecutor();
}
public abstract void doExecutor();
}
//用于给执行的bean传递参数
public class ExecutorContextHolder {
final static ThreadLocal<Object> MAP = new ThreadLocal<>();
public static void set(Object obj) {
MAP.set(obj);
}
public static Object get() {
return MAP.get();
}
public static void remove() {
MAP.remove();
}
}
//具体干事情的类
public class TypeAServiceImpl extends AbstractExecutorServiceImpl {
@Override
public void doExecutor() {
//获取上下文参数
Object obj = ExecutorContextHolder.get();
//执行业务逻辑
}
}
4、执行入口
可以再controller调用service中
public void executorOrder(String type) {
IExecutorService instance= ExecutorFactory.EXECUTOR_MAP.get(type);
if(instance !=null) {
instance.executor();
}
}
总结
在多执行场景是适用,例如申请ecs申请obs执行逻辑是不完全相同的,但是又有一块代码类似,比如申请ecs要执行fun1(),fun2(),fun3(),申请obs要执行fun1(),fun()2。那我们就可以将fun1(),fun2()放入抽象类的executor中,把都需要执行的步骤放里面,不同的写在ecs自己的执行类中。