利用注解实现分发策略

实际开发过程中,实现分发策略的方式有很多中,这里就做一个的案例:

  • 【注】: 如果分配策略的任务比较多可以采用线程池或者异步线程池多任务同时执行,
  • 第一步 创建一个自定注解
@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;
    }
}

最后 反射调用结果如下所示:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值