All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.voovan.tools.aop.AopUtils Maven / Gradle / Ivy

There is a newer version: 4.3.8
Show newest version
package org.voovan.tools.aop;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import org.voovan.tools.TEnv;
import org.voovan.tools.TFile;
import org.voovan.tools.TString;
import org.voovan.tools.aop.annotation.Abnormal;
import org.voovan.tools.aop.annotation.After;
import org.voovan.tools.aop.annotation.Around;
import org.voovan.tools.aop.annotation.Before;
import org.voovan.tools.json.JSON;
import org.voovan.tools.log.Logger;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.regex.Matcher;

/**
 * 切面工具类
 *
 * @author: helyho
 * WebSite: https://github.com/helyho/DBase
 * Licence: Apache v2 License
 */
public class AopUtils {
    public static ClassPool CLASSPOOL = ClassPool.getDefault();
    public static List CUT_POINTINFO_LIST = new ArrayList();

    /**
     * 获取 CtClass 对象
     * @param className CtClass 对象完全现定名
     * @return CtClass 对象
     * @throws NotFoundException 无法找到对一个的 CtClass
     */
    public static CtClass getCtClass(String className) throws
            NotFoundException {
        CtClass ctClass = null;
        ctClass = AopUtils.CLASSPOOL.get(className);
        ctClass.detach();
        return ctClass;
    }

    /**
     * 从当前进程的Javaassist中寻找 Class
     * @param pattern  确认匹配的正则表达式
     * @param filters  过滤的 class, 满足这些条件的 class 才会被搜索到(注解,接口,继承的类)
     * @return  匹配到的 class 集合
     * @throws IOException IO 异常
     */
    public static List searchClassInJavassist(String pattern, Class[] filters) throws IOException {
        String userDir = System.getProperty("user.dir");
        List classPaths = TEnv.getClassPath();
        ArrayList clazzes = new ArrayList();
        for(String classPath : classPaths){
            File classPathFile = new File(classPath);
            if(classPathFile.exists() && classPathFile.isDirectory()){
                clazzes.addAll( getDirectorClass(classPathFile, pattern, filters));
            } else if(classPathFile.exists() && classPathFile.isFile() && classPathFile.getName().endsWith(".jar")) {
                clazzes.addAll( getJarClass(classPathFile, pattern, filters) );
            }
        }

        return clazzes;
    }

    /**
     * 从指定 File 对象寻找 CtClass
     * @param rootfile 文件目录 File 对象
     * @param pattern  确认匹配的正则表达式
     * @param filters  过滤的 class, 满足这些条件的 class 才会被搜索到(注解,接口,继承的类)
     * @return  匹配到的 class 集合
     * @throws IOException IO 异常
     */
    public static List getDirectorClass(File rootfile, String pattern, Class[] filters) throws IOException {
        if(pattern!=null) {
            pattern = pattern.replace(".", File.separator);
        }

        //兼容 windows
        String innerPattern = File.separator.equals("\\") ? Matcher.quoteReplacement(pattern) : pattern;

        ArrayList result = new ArrayList();
        List files = TFile.scanFile(rootfile, innerPattern);
        for(File file : files){
            String fileName = file.getCanonicalPath();
            if("class".equals(TFile.getFileExtension(fileName))) {
                //如果是内部类则跳过
                if(TString.regexMatch(fileName,"\\$\\d\\.class")>0){
                    continue;
                }
                fileName = fileName.replace(rootfile.getCanonicalPath() + File.separator, "");
                try {
                    CtClass clazz = resourceToCtClass(fileName);
                    result.add(clazz);
                } catch (ClassNotFoundException e) {
                    Logger.warn("Try to load class["+fileName+"] failed",e);
                }
            }
        }
        return result;
    }

    /**
     * 从指定jar 文件中寻找 CtClass
     * @param jarFile  jar 文件 File 对象
     * @param pattern  确认匹配的正则表达式
     * @param filters  过滤的 class, 满足这些条件的 class 才会被搜索到(注解,接口,继承的类)
     * @return  匹配到的 class
     * @throws IOException IO 异常
     */
    public static List getJarClass(File jarFile, String pattern, Class[] filters) throws IOException {
        if(pattern!=null) {
            pattern = pattern.replace(".", File.separator);
        }
        ArrayList result = new ArrayList();
        List jarEntrys = TFile.scanJar(jarFile, pattern);
        for(JarEntry jarEntry : jarEntrys){
            String fileName = jarEntry.getName();
            if("class".equals(TFile.getFileExtension(fileName))) {
                //如果是内部类则跳过
                if (TString.regexMatch(fileName, "\\$\\d\\.class") > 0) {
                    continue;
                }

                try {
                    CtClass clazz = resourceToCtClass(fileName);
                    result.add(clazz);
                } catch (Throwable e) {
                    fileName = null;
                }
            }
        }
        return result;
    }

    /**
     * 将资源文件路径 转换成 CtClass
     * @param resourcePath 资源资源文件路径
     * @return Class对象
     * @throws ClassNotFoundException 类未找到异常
     */
    public static CtClass resourceToCtClass(String resourcePath) throws ClassNotFoundException {
        String className = null;

        if(resourcePath.startsWith(File.separator)){
            resourcePath = TString.removePrefix(resourcePath);
        }

        className = TString.fastReplaceAll(resourcePath, "\\$.*\\.class$", ".class");
        className = TString.fastReplaceAll(className, ".class$", "");

        className = TString.fastReplaceAll(className, Matcher.quoteReplacement(File.separator), ".");

        try {
            return CLASSPOOL.get(className);
        }catch (java.lang.Exception ex) {
            throw new ClassNotFoundException("load and define class " + className + " failed");
        }
    }

    /**
     * Javassist 扫描所有的切面注入点
     * @param scanPackage 扫描的包路径
     * @throws IOException IO 异常
     * @throws ClassNotFoundException 类未找到异常
     */
    public static void scanAopClass(String scanPackage) throws IOException, ClassNotFoundException {
        System.out.println("[AOP] Scan from package: " + scanPackage);
        List aopClasses = AopUtils.searchClassInJavassist(scanPackage, new Class[]{org.voovan.tools.aop.annotation.Aop.class});

        for(CtClass clazz : aopClasses){
            CtMethod[] methods = clazz.getDeclaredMethods();
            for(CtMethod cutPointMethod : methods){
                Before onBefore = (Before) cutPointMethod.getAnnotation(Before.class);
                After onAfter = (After)cutPointMethod.getAnnotation(After.class);
                Abnormal onAbnormal = (Abnormal)cutPointMethod.getAnnotation(Abnormal.class);
                Around onAround = (Around)cutPointMethod.getAnnotation(Around.class);

                if(onBefore!=null){
                    CutPointInfo cutPointInfo = CutPointInfo.parse(onBefore.value());
                    cutPointInfo.setType(-1);
                    cutPointInfo.setCutPointMethod(cutPointMethod);
                    cutPointInfo.setInterceptLambda(onBefore.lambda());
                    AopUtils.CUT_POINTINFO_LIST.add(cutPointInfo);
                    System.out.println("[AOP] Add cutpoint: " + JSON.toJSON(cutPointInfo.getClazzName() + "@" + cutPointInfo.getMethodName()));
                }

                if(onAfter!=null){
                    CutPointInfo cutPointInfo = CutPointInfo.parse(onAfter.value());
                    cutPointInfo.setType(1);
                    cutPointInfo.setCutPointMethod(cutPointMethod);
                    cutPointInfo.setInterceptLambda(onAfter.lambda());
                    AopUtils.CUT_POINTINFO_LIST.add(cutPointInfo);
                    System.out.println("[AOP] Add cutpoint: " + JSON.toJSON(cutPointInfo.getClazzName() + "@" + cutPointInfo.getMethodName()));
                }

                if(onAbnormal !=null){
                    CutPointInfo cutPointInfo = CutPointInfo.parse(onAbnormal.value());
                    cutPointInfo.setType(2);
                    cutPointInfo.setCutPointMethod(cutPointMethod);
                    cutPointInfo.setInterceptLambda(onAbnormal.lambda());
                    AopUtils.CUT_POINTINFO_LIST.add(cutPointInfo);
                    System.out.println("[AOP] Add cutpoint: " + JSON.toJSON(cutPointInfo.getClazzName() + "@" + cutPointInfo.getMethodName()));
                }

                if(onAround !=null){
                    CutPointInfo cutPointInfo = CutPointInfo.parse(onAround.value());
                    cutPointInfo.setType(3);
                    cutPointInfo.setCutPointMethod(cutPointMethod);
                    cutPointInfo.setInterceptLambda(onAround.lambda());
                    AopUtils.CUT_POINTINFO_LIST.add(cutPointInfo);
                    System.out.println("[AOP] Add cutpoint: " + JSON.toJSON(cutPointInfo.getClazzName() + "@" + cutPointInfo.getMethodName()));
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy