Java Spring 通过 AOP 实现方法参数的重新赋值、修改方法参数的取值

AOP 依赖

我创建的项目项目为 SpringBoot 项目

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.3</version>
    </parent>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

String 类型参数

这里以对前端传递过来的加密数据进行解密为例

注解

import java.lang.annotation.*;

/**
 * 标注需要进行 RSA 加密算法解密的通用注解。
 * 该注解可以使用在类上、方法上、方法参数上、字段/属性上、局部变量上
 */
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DecodeRsaCommonAnnotation {
}
import java.lang.annotation.*;

/**
 * 标注需要进行 RSA 加密算法解密的方法参数的注解。
 * 该注解可以使用在方法参数上
 */
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DecodeRsaParameterAnnotation {
}

控制器方法

    @GetMapping("/test")
    @DecodeRsaCommonAnnotation
    public void test(
            @DecodeRsaParameterAnnotation
            String text
    ) {
        System.out.println(text);
    }

方式一:通过环绕通知实现 [个人比较推荐]

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Order(1)
@Component
public class DecodeRsaAspect {

    /**
     * DecodeRsaAspect 的切点为被 @DecodeRsaCommonAnnotation 标记的位置
     */
    @Pointcut("@annotation(cn.org.xiaoweiba.graduationdesign.bookmall.annotation.rsa.DecodeRsaCommonAnnotation)")
    public void pointCut() {
    }

    /**
     * 采用 Rsa 加密算法进行解密
     *
     * @param proceedingJoinPoint 切点
     */
    @Around("pointCut()")
    public Object decodeRsaAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
        Object returnVal = null;
        try {
            // 获取切点方法的参数
            Object[] args = proceedingJoinPoint.getArgs();
            // 中间处理 ...
            // 对切点方法的参数进行重新赋值
            for (int i = 0; i < args.length; i++) {
                args[i] = "RSA 加密算法解密后的数据";
            }
            // 执行切点方法,并传递重新赋值后的参数列表
            returnVal = proceedingJoinPoint.proceed(args);
        } catch (Throwable e) {
            // 异常处理 ...
        }
        // 返回切点方法执行后的返回值
        return returnVal;
    }

}

在这里插入图片描述
在这里插入图片描述

方式二:通过前置通知 + 反射实现

Java ReflectUtil 反射相关的工具类

由于 JDK 8 中有关反射相关的功能自从 JDK 9 开始就已经被限制了,如:通过反射修改 String 类型变量的 value 字段(final byte[]),所以要能够使用运行此方法,需要在运行项目时,添加虚拟机(VM)选项:--add-opens java.base/java.lang=ALL-UNNAMED,开启默认不被允许的行为

通过反射修改 String 类型对象 value 取值的工具方法

获取指定对象中的指定字段(不包含父类中的字段)

    /**
     * 获取指定对象中的指定字段(不包含父类中的字段)。
     * 此方法在获取指定对象中的指定字段时,会包证获取的指定字段能够被访问。
     *
     * @param object 要获取字段的指定对象
     * @param fieldName 要获取的指定字段的名称
     * @return 指定对象中的指定字段
     */
    public static Field getField(Object object, String fieldName) throws NoSuchFieldException {
        // 获取指定对象的 Class
        Class<?> objectClass = object.getClass();
        // 获取指定对象中的指定字段
        Field declaredField = objectClass.getDeclaredField(fieldName);
        // 保证获取的指定字段能够被访问
        declaredField.setAccessible(true);
        return declaredField;
    }

通过反射为字符串对象的 value 字段重新赋值为 strValue

    /**
     * 通过反射为字符串对象的 value 字段重新赋值为 strValue,
     * 从而保证不修改字符串对象的引用,并且能够修改字符串的取值
     * 由于 JDK 8 中有关反射相关的功能自从 JDK 9 开始就已经被限制了,所以要能够使用运行此方法,
     * 需要在运行项目时,添加虚拟机(VM)选项:--add-opens java.base/java.lang=ALL-UNNAMED
     * 开启默认不被允许的行为
     *
     * @param str 需要进行重新赋值的字符串对象
     * @param strValue 要赋值给字符串对象的值
     */
    public static void setValueString(String str, String strValue) throws NoSuchFieldException, IllegalAccessException {
        // 获取字符串的 value 字段
        Field strValueField = getField(str, "value");
        // 为字符串对象的 value 字段重新赋值
        // strValueField.set(str, strValue.getBytes(StandardCharsets.UTF_8)); 不要使用该种方法,会出现乱码
        // 采用如下方式,获取 strValue 的 value 字段值,将其赋值给 str 的 value 字段
        strValueField.set(str, strValueField.get(strValue));
    }
切面类
import cn.org.xiaoweiba.graduationdesign.bookmall.utils.ReflectUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Order(1)
@Component
public class DecodeRsaAspect {

    /**
     * DecodeRsaAspect 的切点为被 @DecodeRsaCommonAnnotation 标记的位置
     */
    @Pointcut("@annotation(cn.org.xiaoweiba.graduationdesign.bookmall.annotation.rsa.DecodeRsaCommonAnnotation)")
    public void pointCut() {
    }

    /**
     * 采用 Rsa 加密算法进行解密
     *
     * @param joinPoint 切点
     */
    @Before("pointCut()")
    public void decodeRsaBeforeAdvice(JoinPoint joinPoint) {
        try {
            // 获取切点方法的参数
            Object[] args = joinPoint.getArgs();
            // 中间处理 ...
            // 对切点方法的参数进行重新赋值
            for (int i = 0; i < args.length; i++) {
                // 对字符串对象的 value 字段重新赋值,不修改字符串对象的指向,保证修改的为切点方法的字符串对象参数
                ReflectUtil.setValueString((String) args[i], "解密后的数据");
            }
        } catch (Throwable e) {
            // 异常处理 ...
        }
    }

}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

### CNN卷积核的空间不变性 卷积神经网络(CNN)中的卷积操作具备空间不变性的特性,这意味着无论特征出现在输入数据的哪个位置,只要该模式存在,模型都能识别出来[^1]。具体来说,在卷积过程中使用的滤波器(即卷积核)在整个图像上滑动并执行相同的操作,这使得同一组权重能够检测到不同位置上的相似图案或边缘。 这种机制允许CNN自动学习如何捕捉平移不变性——即使目标物体在图片的不同区域移动,仍然能被正确分类。例如,如果一张照片里有一只猫位于画面左侧还是右侧并不影响最终判断其为“猫”。因此,通过共享权值的方式实现了高效而强大的表示能力。 ### 卷积核的冗余性及其影响 关于卷积核中存在的潜在冗余现象,研究表明并非所有的通道都对特定任务有用;某些过滤器可能携带重复的信息或者贡献较小。当多个卷积核捕获几乎相同的视觉模式时就会形成所谓的“冗余”。 一方面,过多不必要的参数不仅增加了计算成本还可能导致过拟合问题的发生。另一方面,适当减少这些无意义连接有助于简化架构设计、加速训练过程以及提高泛化性能。为了应对这种情况,研究者们提出了诸如剪枝(pruning)[^2]等技术来消除不重要的连接从而构建更紧凑有效的模型。 ```python import torch.nn as nn class PrunedCNN(nn.Module): def __init__(self, num_classes=10): super(PrunedCNN, self).__init__() # 假设这里已经应用了一些方法去除了部分冗余卷积核 self.conv1 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3) def forward(self, x): x = F.relu(self.conv1(x)) return x ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值