反射----拈花指

前言

怎麼進一步用反射,在BeanFactoryPostProcessor 做做文章    
## 調用
 public void testRpcRouter(String methodTyep,String typeCode) throws Exception {

        DemoDO demoDO = new DemoDO();
        AbstractHandler abstractHandler = handlerContext.getInstance(typeCode);
        abstractHandler.rpc(demoDO);

        //利用 方法上的 註解,指定執行的方法
        Method method = handlerContext.getMethodInstance(methodTyep);
        method.invoke(new MethodList(), demoDO);
    }

加載

@Component
public class HandlerProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        Map<String, Class> map = Maps.newHashMapWithExpectedSize(2);
        Map<String, Method> methodMap = Maps.newHashMapWithExpectedSize(2);

        List<Class<?>> scan =AnnotationScannerUtils.scan("com.domain.cls", HandlerType.class);
        for (Class<?> clazz : scan) {
            String type = ((HandlerType) clazz.getAnnotation(HandlerType.class)).value();
            map.put(type, clazz);
        }

        List<Method> methods =AnnotationScannerUtils.scanMethodByAnnotation(MethodList.class, MethodType.class);
        for (Method item : methods) {
            String type = ((MethodType) item.getAnnotation(MethodType.class)).value();
            methodMap.put(type, item);

        }
        configurableListableBeanFactory.registerResolvableDependency(HandlerContext.class, new HandlerContext(map, methodMap));
    }
}

自定義的註解

@Documented
@Inherited
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodType {
    String value();
}

@Documented
@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface HandlerType {

    String value();

}

容器


public class HandlerContext {

    private Map<String, Class> map;

    private Map<String, Method> methodMap;

    public HandlerContext(Map<String, Class> map, Map<String, Method> methodMap) {
        this.map = map;
        this.methodMap = methodMap;
    }

    public  AbstractHandler getInstance(String type) {
        Class c = map.get(type);
        return ( AbstractHandler) SpringFactoryUtil.getBean(c);
    }

    public Method getMethodInstance(String type) {
        Method c = methodMap.get(type);
        return c;
    }

}

掃描

package com.ly.fn.xxd.srv.domain;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;

public class AnnotationScannerUtils {
    private static final Logger logger = LoggerFactory.getLogger(com.ly.fn.xxd.srv.domain.AnnotationScannerUtils.class);
    private static final String EXT = "class";


    /**
     * 項目在硬盤上的基礎路徑
     */
    private static final String PROJECT_PATH = System.getProperty("user.dir");// xxd\IdeaProjects\offers
    /**
     * 獲取當前類的路徑 com.example.CodeGenerator.core
     */
    private static String packAge = com.ly.fn.xxd.srv.domain.AnnotationScannerUtils.class.getPackage().getName();
    /**
     * 根據路徑切割最後一位名稱獲得當前類上一級路徑 com.example.CodeGenerator
     */
    private static final String PACKAGE = packAge.substring(0, packAge.lastIndexOf("."));


    /**
     * 自定義方法
     * 將獲取到的包路徑中的點號換成斜槓
     *
     * @param packageName 傳入的包路徑
     * @return 路徑前後都加上斜槓中間也替換成斜槓返回
     */
    private static String packageConvertPath(String packageName) {
        return String.format("/%s/", packageName.contains(".") ? packageName.replaceAll("\\.", "/") : packageName);
    }


    /**
     * 根據包名獲取包的URL
     *
     * @param pkgName com.demo.controller
     * @return
     */
    public static String getPkgPath(String pkgName) {
        String pkgDirName = pkgName.replaceAll("\\.", "/");
        URL url = Thread.currentThread().getContextClassLoader().getResource(pkgDirName);

        return url == null ? null : url.getFile();
    }


    public static List<Class<?>> scan(String pkgName, Class<? extends Annotation> Annotation) {
        Set<Class<?>> set = scanClasses(pkgName, getPkgPath(pkgName), false);
        List<Class<?>> result = new ArrayList<>();
        for (Class<?> aClass : set) {
            if (aClass.isAnnotationPresent(Annotation)) {
                result.add(aClass);
            }
        }
        return result;
    }


    /**
     * 獲取指定包下所有類對象的集合
     *
     * @param pkgName   包名(com.demo.controller)
     * @param pkgPath   包路徑(/Users/xxx/workspace/java/project/out/production/classes/com/demo/controller)
     * @param recursive 是否遞歸遍歷子目錄
     * @return 類集合
     */
    public static Set<Class<?>> scanClasses(String pkgName, String pkgPath, final boolean recursive) {
        Set<Class<?>> classesSet = new HashSet<>();

        Collection<File> allClassFile = getAllClassFile(pkgPath, recursive);


        for (File curFile : allClassFile) {
            try {
                classesSet.add(getClassObj(curFile, pkgPath, pkgName));
            } catch (ClassNotFoundException e) {
                logger.error("load class fail", e);
            }
        }

        return classesSet;
    }

    /**
     * 獲取指定包下包含指定註解的所有類對象的集合
     *
     * @param pkgName           包名(com.demo.controller)
     * @param pkgPath           包路徑(/Users/xxx/workspace/java/project/out/production/classes/com/demo/controller)
     * @param recursive         是否遞歸遍歷子目錄
     * @param targetAnnotations 指定註解
     * @return 以註解和對應類集合構成的鍵值對
     */
    public static Map<Class<? extends Annotation>, Set<Class<?>>> scanClassesByAnnotations(
            String pkgName, String pkgPath, final boolean recursive, List<Class<? extends Annotation>> targetAnnotations) {
        Map<Class<? extends Annotation>, Set<Class<?>>> resultMap = new HashMap<>(16);

        Collection<File> allClassFile = getAllClassFile(pkgPath, recursive);

        for (File curFile : allClassFile) {
            try {
                Class<?> curClass = getClassObj(curFile, pkgPath, pkgName);
                for (Class<? extends Annotation> annotation : targetAnnotations) {
                    if (curClass.isAnnotationPresent(annotation)) {
                        if (!resultMap.containsKey(annotation)) {
                            resultMap.put(annotation, new HashSet<Class<?>>());
                        }
                        resultMap.get(annotation).add(curClass);
                    }
                }
            } catch (ClassNotFoundException e) {
                logger.error("load class fail", e);
            }
        }

        return resultMap;
    }

    /**
     * 加載類
     *
     * @param file
     * @param pkgPath
     * @param pkgName
     * @return
     * @throws ClassNotFoundException
     */
    private static Class<?> getClassObj(File file, String pkgPath, String pkgName) throws ClassNotFoundException {
        // 考慮class文件在子目錄中的情況
        String absPath = file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - EXT.length() - 1);
        String className = absPath.substring(pkgPath.length()).replace(File.separatorChar, '.');
        className = className.startsWith(".") ? pkgName + className : pkgName + "." + className;

        return Thread.currentThread().getContextClassLoader().loadClass(className);
    }

    /**
     * 遍歷指定目錄下所有擴展名爲class的文件
     *
     * @param pkgPath   包目錄
     * @param recursive 是否遞歸遍歷子目錄
     * @return
     */
    private static Collection<File> getAllClassFile(String pkgPath, boolean recursive) {
        File fPkgDir = new File(pkgPath);

        if (!(fPkgDir.exists() && fPkgDir.isDirectory())) {
            logger.error("the directory to package is empty: {}", pkgPath);

            return null;
        }

        return FileUtils.listFiles(fPkgDir, new String[]{EXT}, recursive);
    }

    /**
     * 查找指定註解的Method
     *
     * @param classes    查找範圍
     * @param annotation 指定的註解
     * @return 以註解和對應Method類集合構成的鍵值對
     */
    public static List<Method> scanMethodByAnnotation(Class<?> classes, Class<? extends Annotation> annotation) {
        List<Method> list = new ArrayList<>();
        Method[] methods = classes.getMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(annotation)) {
                list.add(method);
            }
        }
        return list;
    }


    /**
     * 查找指定註解的Method
     *
     * @param classes           查找範圍
     * @param targetAnnotations 指定的註解
     * @return 以註解和對應Method類集合構成的鍵值對
     */
    public static Map<Class<? extends Annotation>, Set<Method>> scanMethodsByAnnotations(Set<Class<?>> classes,
                                                                                         List<Class<? extends Annotation>> targetAnnotations) {
        Map<Class<? extends Annotation>, Set<Method>> resultMap = new HashMap<>(16);

        for (Class<?> cls : classes) {
            Method[] methods = cls.getMethods();

            for (Class<? extends Annotation> annotation : targetAnnotations) {
                for (Method method : methods) {
                    if (method.isAnnotationPresent(annotation)) {
                        if (!resultMap.containsKey(annotation)) {
                            resultMap.put(annotation, new HashSet<Method>());
                        }
                        resultMap.get(annotation).add(method);
                    }
                }
            }
        }

        return resultMap;
    }
}

具體實現類

方法級別

類級別

在這裏插入圖片描述

整體

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章