实际开发过程中,实现分发策略的方式有很多中,这里就做一个的案例:
- 【注】: 如果分配策略的任务比较多可以采用线程池或者异步线程池多任务同时执行,
- 第一步 创建一个自定注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyMethodAnnotation {
String value();
}
- 第二步 创建封装对象
import java.lang.reflect.Method;
public class ActionEntity {
/**
* 注解所对应的类
*/
private Class<?> klass;
/**
* 注解对应的方法
*/
private Method method;
/**
* 需要执行的策略类型
*/
private String policy;
/**
* 提前创建的执行对象
*/
private Object executeMethod;
public ActionEntity(Class<?> klass, Method method, Object executeMethod,String policy) {
this.klass = klass;
this.method = method;
this.policy = policy;
this.executeMethod = executeMethod;
}
public Class<?> getKlass() {
return klass;
}
public void setKlass(Class<?> klass) {
this.klass = klass;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public String getPolicy() {
return policy;
}
public void setPolicy(String policy) {
this.policy = policy;
}
public Object getExecuteMethod() {
return executeMethod;
}
public void setExecuteMethod(Object executeMethod) {
this.executeMethod = executeMethod;
}
}
- 第三步 实现注解扫描
import basics.annotation.Actioner;
import basics.scanner.model.ActionEntity;
import org.springframework.stereotype.Component;
import java.io.File;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.*;
import java.util.jar.JarEntry;
@Component
public class AnnotationScanner {
List<ActionEntity> actionEntityList = new ArrayList<>();
List<String> classFileList = new ArrayList<>();
public static final String type;
static {
type = "\\";
}
public List<ActionEntity> scanner() throws Exception {
// URL resource = Objects.requireNonNull(ClassUtils.getDefaultClassLoader()).getResource("com/auth/practice/application");
URL resource = this.getClass().getClassLoader().getResource("basics");
if (null == resource) {
throw new RuntimeException("加载资源异常");
}
classFileList.clear();
String property = System.getProperty("os.name").toUpperCase();
List<Class> classList = new ArrayList<>();
if (property.startsWith("WINDOWS")) {
getWindowsInfo(resource, classList);
}
if (property.startsWith("LINUX")) {
getLinuxInfo(resource, classList);
}
return actionEntityList;
}
private void getLinuxInfo(URL url, List<Class> classList) throws Exception {
Enumeration<JarEntry> jarEntries = ((JarURLConnection) url.openConnection())
.getJarFile().entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarName = jarEntry.getName();
if (!jarEntry.isDirectory() && jarName.endsWith(".class")) {
// 将文件路径名转换为包名称的形式
classFileList.add(jarName);
}
}
getClassPath(classList);
getMethod(classList);
}
private void getWindowsInfo(URL resource, List<Class> classList) throws Exception {
String packAgePath = resource.getFile();
File[] files = new File(packAgePath).listFiles(pathName -> (pathName.isFile() && pathName.getName().endsWith(".class") || pathName.isDirectory()));
for (File file : files) {
getClassFile(file);
}
getClassPath(classList);
getMethod(classList);
}
private void getMethod(List<Class> classList) throws IllegalAccessException, InstantiationException {
for (Class aClass : classList) {
Method[] methods = aClass.getMethods();
for (Method method : methods) {
Actioner annotation = method.getAnnotation(Actioner.class);
if (null == annotation) {
continue;
}
actionEntityList.add(new ActionEntity(aClass,method,aClass.newInstance(),annotation.action()));
}
}
}
private void getClassPath(List<Class> classList) throws ClassNotFoundException {
for (String classPath : classFileList) {
if (classPath.contains("/")) {
String[] targetClassPath = classPath.split("classes/");
Class<?> aClass = Class.forName(targetClassPath[1].replace(".class", ""));
if (!aClass.isAnnotation() && !aClass.isInterface() && !aClass.isEnum() && !aClass.isPrimitive()) {
classList.add(aClass);
}
}
if (classPath.contains(type)) {
classPath = classPath.replace(type, ".");
String[] targetClassPath = classPath.split("classes\\.");
Class<?> aClass = Class.forName(targetClassPath[1].replace(".class", ""));
if (!aClass.isAnnotation() && !aClass.isInterface() && !aClass.isEnum() && !aClass.isPrimitive()) {
classList.add(aClass);
}
}
}
}
private void getClassFile(File file) {
if (file.getName().endsWith(".class")) {
classFileList.add(file.getName());
} else {
File[] files = file.listFiles(pathName -> (pathName.isFile() && pathName.getName().endsWith(".class") || pathName.isDirectory()));
for (File subFile : files) {
if (!subFile.getName().endsWith(".class")) {
getClassFile(subFile);
} else {
classFileList.add(subFile.getPath());
}
}
}
}
}
- 第四步 创建分发器
@Component
public class PolicyDispatcher {
public void dispatcher(Map<String, Object> dataMap) {
try {
List<String> policy = (List<String>) paramMap.get("policy");
Map<String, String> policyMap = policy.stream().collect(Collectors.toMap(string -> string, string -> string));
for (ActionEntity actionEntity : scanner) {
if (policyMap.containsKey(actionEntity.getPolicy())) {
try {
Class<?> klass = actionEntity.getKlass();
Method method = klass.getMethod(actionEntity.getMethod().getName(), Map.class);
Object invoke = method.invoke(actionEntity.getExecuteMethod(), paramMap);
System.out.println("invoke" + invoke);
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 第五步 在被分发的方法上打上注解 和注解属性
public class PolicyMethod {
@Actioner(action = "MONDAY")
public Map<String, Object> executePolicyOne(Map<String, Object> parameter) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("ok", "等待时间为 100 毫秒 -> 执行完毕");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
dataMap.putAll(parameter);
return dataMap;
}
@Actioner(action = "HELLO")
public Map<String, Object> executeHello(Map<String, Object> parameter) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("ok", "等待时间为 200 毫秒 -> 执行完毕");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
dataMap.putAll(parameter);
return dataMap;
}
@Actioner(action = "TUESDAY")
public Map<String, Object> executeTuesday(Map<String, Object> parameter) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("ok", "等待时间为 300 毫秒 -> 执行完毕");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
dataMap.putAll(parameter);
return dataMap;
}
}
最后 反射调用结果如下所示: