注解&反射&切面

下拉框选择自定义的方法,然后去反射

定义注解类

@Documented
@Retention(RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD })//作用在类和方法上
public @interface YjsOutWay
{

    String wayName() default "";
    // 注解说明
    // https://blog.csdn.net/javazejian/article/details/71860633
}

相关类和方法加注解

@Service
@YjsOutWay
public class ZgYjsOutWayService
{

    private ZgYjsCommonService zgYjsCommonService = ContainerFactory.getContainInfo().getComponent(ZgYjsCommonService.class);

    @YjsOutWay(wayName = "通用业务信息保存")
    public JSONObject saveCommonYw(String param) {
        JSONObject jsonObject = JSONObject.fromObject(param);
        String userGuids = jsonObject.optString("userguids");
        if (StringUtil.isBlank(userGuids)) {
            return null;
        }
        if (userGuids.endsWith(",")) {
            userGuids = userGuids.substring(0, userGuids.length() - 1);
        }
        String joinPoliceType = jsonObject.optString("joinpolicetype");
        return zgYjsCommonService.saveCommonYw(userGuids, joinPoliceType);
    }
    }

获取包下所有加了注解的类

public class HrClassUtil extends ClassUtil
{
    private static final Logger log = LoggerFactory.getLogger(HrClassUtil.class);
    /**
     * 静态缓存所有包下的class
     */
    private static List<Class<?>> allGaClass = null;

    /**
     * 默认包路径
     */
    public static String DefaultPackageName = "com.xx.xx";

    /***
     * 获取到包路径下class自身、子类、实现类
     * 
     * @param c
     * @param packageName
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes" })
    public static List<Class> getAllClassByInterface(Class c, String packageName) {
        // log.info("getAllClassByInterface:" + c + "=======" + packageName);
        // 返回的classList
        List<Class> returnClassList = new ArrayList<>();

        // 不是接口,或者包路径为空
        if (!c.isInterface() || StringUtil.isBlank(packageName)) {
            log.info("包路径为空,class非接口");
            return returnClassList;
        }

        // 扫描到的class
        List<Class<?>> searchClass = null;
        // 如果类名就是全路径,静态缓存,再赋值
        if (DefaultPackageName.equals(packageName)) {
            // 初始化 路径下的所有类
            if (allGaClass == null) {
                // 第一次的时候,缓存所有
                allGaClass = HrClassUtil.getClasses(DefaultPackageName);
            }
            searchClass = allGaClass;
        }
        else {
            // 获取包下面的类
            searchClass = HrClassUtil.getClasses(packageName);
        }

        if (CollectionUtils.isEmpty(searchClass)) {
            return returnClassList;
        }

        Iterator<Class<?>> var4 = searchClass.iterator();
        while (var4.hasNext()) {
            Class<T> classes = (Class) var4.next();
            // c是的classes父类 && !c.equals(classes)
            if (c.isAssignableFrom(classes) && !c.equals(classes)) {
                returnClassList.add(classes);
            }
        }

        return returnClassList;
    }

    /**
     * 获取包下面所有具XX注解的类
     * 
     * @param c
     * @param packageName
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes" })
    public static Set<Class<?>> getAllClassByTypeAnnotation(Class annotationCls, String packageName) {
        // log.info("getAllClassByTypeAnnotation:" + annotationCls + "=======" + packageName);
        // 要扫描的包名
        Reflections f = new Reflections(packageName);
        // 目标注解类
        // Set<Class<?>> set = f.getTypesAnnotatedWith(annotationCls);
        return f.getTypesAnnotatedWith(annotationCls);
    }

}

获取加了注解的方法,和反射的工具类

public class ZgYjsUtil
{

    /**
     * 静态缓存包下的方法
     */
    private static List<Record> allMenthodList = null;

    public static final String packageName = "com.xx.xx";

    /**
     * 通过反射信息获取方法执行后的结果
     *
     * @param reflectInfo
     *            例如:com.xxx.className.methodName
     * @return 反射方法获取的结果,获取不到结果则返回空
     */
    public static String getReflect(String reflectInfo, Object... args) {
        int index = reflectInfo.lastIndexOf('.');
        if (index == -1) {
            throw new IllegalArgumentException("反射信息格式不正确!");
        }

        String signature = reflectInfo;

        try {
            Object o = ReflectUtils.newInstance(Class.forName(signature.substring(0, index)));

            Object value = null;
            if (args == null || args.length == 0) {
                Method method = ReflectUtils.findMethod(signature);
                value = method.invoke(o);
            }
            else {
                // 获取带多个参数
                signature += "(String)";
                Method method = ReflectUtils.findMethod(signature);
                value = method.invoke(o, args);
            }

            if (value == null) {
                return "";
            }
            return value.toString();
        }
        catch (Exception e) {
            return "";
        }
    }

    // 调用
    // getYjsOutWayListByType("com.xx");
    /**
     * 获取类下的所有具有YjsOutWay注解的方法
     * 
     * @param typeClass
     * @param annotationClass
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static List<Record> getYjsOutWayListByType(String packageName) {
        List<Record> recordList = new ArrayList<>();
        // 全局缓存,已有就不查
        if (CollectionUtils.isNotEmpty(allMenthodList)) {
            recordList = allMenthodList;
            return recordList;
        }
        Set<Class<?>> yjsTypeClass = HrClassUtil.getAllClassByTypeAnnotation(YjsOutWay.class, packageName);
        if (CollectionUtils.isNotEmpty(yjsTypeClass)) {
            for (Class<?> yjsClass : yjsTypeClass) {
                recordList.addAll(getMenthByYjsAnnotation(yjsClass));
            }
        }
        allMenthodList = recordList;
        return recordList;
    }

    /**
     * 获取类下的所有具有YjsOutWay注解的方法
     * 
     * @param typeClass
     * @param annotationClass
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static List<Record> getMenthByYjsAnnotation(Class typeClass) {
        // 获取当前类所有方法
        List<Record> recordList = new ArrayList<>();
        Method[] declaredMethods = typeClass.getDeclaredMethods();
        if (declaredMethods != null && declaredMethods.length > 0) {
            for (Method method : declaredMethods) {
                // 获取当前类有注解的方法
                if (method.isAnnotationPresent(YjsOutWay.class)) {
                    YjsOutWay annotation = method.getAnnotation(YjsOutWay.class);
                    Record record = new Record();
                    record.set("path", method.getDeclaringClass().getName() + "." + method.getName());
                    record.set("name", annotation.wayName() + "[" + record.get("path") + "]");
                    recordList.add(record);
                }
            }
        }
        return recordList;
    }

}

找所有实现此接口的所有实现类

public class HrInterfaceUtil
{

    private static final Logger log = Logger.getLogger(HrInterfaceUtil.class);

    /**
     * 获取自定义并实现HrCustom注解的class
     * 
     * @author YHH
     * @param clazz
     * @packagePath 【com.xx.xx.hr.annotation】
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked" })
    public static <T> T getCustomizeClass(Class<?> clazz, String packagePath) {
        // 返回的class
        T resultClass = null;

        if (StringUtil.isBlank(packagePath)) {
            return null;
        }

        // 获取clazz的所有接口实现类xx
        List<Class> interfaceClassList = HrClassUtil.getAllClassByInterface(clazz, packagePath);
        if (CollectionUtils.isEmpty(interfaceClassList)) {
            // log.error("#####未发现相关类#####");
            return resultClass;
        }
        // 是否有注解判断
        int customizeNum = 0;
        try {
            for (Class<T> cls : interfaceClassList) {
                // 加了注解
                // 判断该实现类是否有注解
                HrCustom hrCustom = cls.getAnnotation(HrCustom.class);
                // 给resultClass 定义一个初始的实体类
                if (resultClass == null) {
                    // 默认产品的
                    resultClass = cls.newInstance();
                }
                if (hrCustom != null) {
                    resultClass = cls.newInstance();
                    customizeNum++;
                }
            }

            if (customizeNum > 1) {
                log.error("#####该接口的个性化实现类超过一个,无法确认哪一个,请确定接口实现是否正确#####");
                return null;
            }

            return resultClass;
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取自定义的class,默认自身接口
     * 
     * @author xx
     * @param clazz
     * @packagePath 【com.xx.xx.hr.annotation】
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked" })
    public static <T> T getCustomImplClass(Class<?> clazz, String packagePath) {
        try {
            // 返回的class,默认自身
            T resultClass = null;

            if (StringUtil.isBlank(packagePath)) {
                return resultClass;
            }

            // 获取clazz的所有接口实现类【产品自身的,项目个性化的】
            List<Class> interfaceClassList = HrClassUtil.getAllClassByInterface(clazz, packagePath);
            if (CollectionUtils.isEmpty(interfaceClassList)) {
                log.error("#####未发现相关类#####");
                return resultClass;
            }

            int customizeNum = 0;
            for (Class<T> cls : interfaceClassList) {
                resultClass = cls.newInstance();
                customizeNum++;
            }

            if (customizeNum > 1) {
                log.error("#####该接口的个性化实现类超过一个,无法确认哪一个,请确定接口实现是否正确#####");
                return resultClass;
            }

            return resultClass;
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

AOP

AOP的基本概念

Advice(通知、切面): 某个连接点所采用的处理逻辑,也就是向连接点注入的代码, AOP在特定的切入点上执行的增强处理。

1.1 @Before: 标识一个前置增强方法,相当于BeforeAdvice的功能.
1.2 @After: final增强,不管是抛出异常或者正常退出都会执行.
1.3 @AfterReturning: 后置增强,似于AfterReturningAdvice, 方法正常退出时执行.
1.4 @AfterThrowing: 异常抛出增强,相当于ThrowsAdvice.
1.5 @Around: 环绕增强,相当于MethodInterceptor.

JointPoint(连接点):程序运行中的某个阶段点,比如方法的调用、异常的抛出等。

Pointcut(切入点): JoinPoint的集合,是程序中需要注入Advice的位置的集合,指明Advice要在什么样的条件下才能被触发,在程序中主要体现为书写切入点表达式。

Advisor(增强): 是PointCut和Advice的综合体,完整描述了一个advice将会在pointcut所定义的位置被触发。

@Aspect(切面): 通常是一个类的注解,里面可以定义切入点和通知

AOP Proxy:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

原文链接:https://blog.csdn.net/baidu_37366055/article/details/109989145

由下列方式来定义或者通过 &&、 ||、 !、 的方式进行组合:

execution:用于匹配方法执行的连接点;
within:用于匹配指定类型内的方法执行;
this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
@within:用于匹配所以持有指定注解类型内的方法;
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
@args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
@annotation:用于匹配当前执行方法持有指定注解的方法;
eg.

任意公共方法的执行:execution(public * (…))
任何一个以“set”开始的方法的执行:execution(
set*(…))
AccountService 接口的任意方法的执行:execution(* com.xyz.service.AccountService.(…))
定义在service包里的任意方法的执行: execution(
com.xyz.service…(…))
定义在service包和所有子包里的任意类的任意方法的执行:execution(* com.xyz.service….(…))
第一个表示匹配任意的方法返回值, …(两个点)表示零个或多个,第一个…表示service包及其子包,第二个表示所有类, 第三个表示所有方法,第二个…表示方法的任意参数个数
定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:execution(
com.test.spring.aop.pointcutexp…JoinPointObjP2.(…))")
pointcutexp包里的任意类: within(com.test.spring.aop.pointcutexp.
)
pointcutexp包和所有子包里的任意类:within(com.test.spring.aop.pointcutexp…*)
实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类:this(com.test.spring.aop.pointcutexp.Intf)
当一个实现了接口的类被AOP的时候,用getBean方法必须cast为接口类型,不能为该类的类型
带有@Transactional标注的所有类的任意方法:
@within(org.springframework.transaction.annotation.Transactional)
@target(org.springframework.transaction.annotation.Transactional)
带有@Transactional标注的任意方法:@annotation(org.springframework.transaction.annotation.Transactional)
@within和@target针对类的注解,@annotation是针对方法的注解
参数带有@Transactional标注的方法:@args(org.springframework.transaction.annotation.Transactional)
参数为String类型(运行是决定)的方法: args(String)

基于注解的AOP

在这里插入图片描述

@Documented
@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface VerifyEncryptionConfig
{

}

编写切面

@Aspect
@Component
public class VerifyEncryptionAspect
{

    @Pointcut("@within(com.xx.xx.zx.server.restful.rest.VerifyEncryptionConfig)")
    public void doVerifyEncryption() {
    }

    /**
     * 标识一个前置增强方法,相当于BeforeAdvice的功能(执行rest接口前相关处理)
     * 
     * author wgd
     * 
     * @param joinPoint
     */
    @Before(value = "doVerifyEncryption()")
    public void doBefore(JoinPoint joinPoint) {
        // 输入的激活码
        String cdkeyInput = PVerifyEncryptionUtil.getEncryptionNumber();
        if (StringUtil.isBlank(cdkeyInput)) {
            ApiBaseController.buildErrorResponse("激活码验证失败!注册码为:" + PVerifyEncryptionUtil.getMainboardEncryption(PVerifyEncryptionUtil.SCENE_NUMBER));
            throw new ParamCheckException("激活码验证失败!注册码为:" + PVerifyEncryptionUtil.getMainboardEncryption(PVerifyEncryptionUtil.SCENE_NUMBER));
        }
        // 生成的激活码
        String cdkReal = PVerifyEncryptionUtil.getFinalEncryptionNumber(PVerifyEncryptionUtil.SCENE_NUMBER);
        if (!cdkeyInput.equals(cdkReal)) {
            ApiBaseController.buildErrorResponse("激活码验证失败!注册码为:" + PVerifyEncryptionUtil.getMainboardEncryption(PVerifyEncryptionUtil.SCENE_NUMBER));
            throw new ParamCheckException("激活码验证失败!注册码为:" + PVerifyEncryptionUtil.getMainboardEncryption(PVerifyEncryptionUtil.SCENE_NUMBER));
        }
    }
}

使用切面

@VerifyEncryptionConfig
@RestController
@RequestMapping("/xxserver")
public class PFdOutServer
{

    private static final Logger log = Logger.getLogger(PFdOutServer.class);

    /**
     * 心跳检测
     */
    @GetMapping("/ping")
    public PResponse ping() {
        log.debug("心跳检测");
        return PResponse.success();
    }
    }

加解密注册码实现

public class PVerifyEncryptionUtil
{

    private static final Logger log = Logger.getLogger(PVerifyEncryptionUtil.class);

    private static final String MVN_TAG = "target/classes/";
    /**
     * 盐值 xx
     * 
     * [test]
     */
    public static final String SALT = "xx";
    /**
     * 场景号
     */
    public static final String SCENE_NUMBER = "fastdeal";

    /**
     * 获取主板序列号
     * 
     * @return
     */
    public static String getMainboardNumber() {
        Runtime runtime = Runtime.getRuntime();
        StringBuffer b = new StringBuffer();
        String mainboardNumber = "";
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(runtime.exec("wmic bios get serialnumber").getInputStream()));
            String line = null;

            while ((line = br.readLine()) != null) {
                b.append(line);
            }
            if (StringUtil.isBlank(b.toString())) {
                return mainboardNumber;
            }
            // 截取到主板号
            String string = b.toString().replace(" ", "");
            String[] strs = string.split("SerialNumber");
            if (strs != null && strs.length > 0) {
                mainboardNumber = strs[1];
            }
        }
        catch (Exception e) {
            log.error("获取主板信息出错", e);
        }
        return mainboardNumber;
    }

    /**
     * 主板号加密后和场景号一起加密
     * 
     * @param sceneNumber
     *            场景号
     * @return
     */
    public static String getMainboardEncryption(String sceneNumber) {
        if (StringUtil.isBlank(sceneNumber)) {
            return "";
        }
        return SM3Util.encrypt(SM3Util.encrypt(getMainboardNumber()) + sceneNumber);

    }

    /**
     * 最终加密字符串
     * 
     * @param sceneNumber
     * @return
     */
    public static String getFinalEncryptionNumber(String sceneNumber) {
        if (StringUtil.isBlank(sceneNumber)) {
            return "";
        }
        return SM3Util.encrypt(getMainboardEncryption(sceneNumber) + SALT);
    }

    /**
     * 根据主办号+盐加密
     * 
     * @param sceneNumber
     * @return
     */
    public static String encryptionByMainBoard(String mainBoard) {
        if (StringUtil.isBlank(mainBoard)) {
            return "";
        }
        return SM3Util.encrypt(mainBoard + SALT);
    }

    /**
     * 写入加密文件
     * 
     * @param encryptionNumber
     */
    public static void createEncryptionFile(String encryptionNumber) {
        if (StringUtil.isBlank(encryptionNumber)) {
            return;
        }
        FileManagerUtil.writeContentToFile(getLicPath(), "xx.lic", encryptionNumber);
    }

    /**
     * 计算路径
     * 
     * @return
     */
    public static String getLicPath() {
        String licPath = ClassPathUtil.getLibPath();

        URL url = SerialN.class.getResource("/");
        String clsPath = url.getFile();
        if (clsPath.indexOf(MVN_TAG) > 0) {// 对于maven工程的特殊判断
            int index = clsPath.indexOf(MVN_TAG);
            if (index != -1) {
                licPath = clsPath.substring(0, index) + "src/main/resources/";
            }
            return licPath;
        }

        return licPath;
    }

    /**
     * 获取加密文件内容
     * 
     * @return
     */
    public static String getEncryptionNumber() {
        if (FileManagerUtil.isExist(getLicPath() + "xx.lic", false)) {
            return FileManagerUtil.getContentFromSystemByReader(getLicPath() + "xx.lic");
        }

        return "";
    }

    /**
     * 获取场景号
     * 
     * @param fileName
     * @param configName
     * @return
     */
    public String getSceneNumber(String fileName, String configName) {
        return ConfigUtil.getConfigValue(fileName, configName);
    }

    /**
     * 验证密码文件
     * 
     * @param sceneNumber
     * @return
     */
    public static boolean verifyPassWord(String sceneNumber) {
        return getFinalEncryptionNumber(sceneNumber).equals(getEncryptionNumber());
    }

    /**
     * main
     * 
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(encryptionByMainBoard("zz"));
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值