java动态代理(jdk/cglib)或spring aop可在方法调用前后自动加解密:通过注解标记参数/返回值,invocationhandler或methodinterceptor拦截处理,注意null、类型、异常等细节,并结合配置中心管理密钥。

Java 中可以通过动态代理(如 JDK 动态代理或 CGLIB)在方法调用前后自动对入参加密、对返回值解密,核心在于拦截方法执行时机并注入加解密逻辑。关键不是“代理本身加密”,而是利用代理的 InvocationHandler 或 MethodInterceptor 在反射调用前/后处理参数和结果。
使用 JDK 动态代理 + 注解控制加解密
适用于接口代理场景,需定义注解标记哪些参数/返回值需要加解密:
- 定义注解:
@EncryptParam标记需加密的参数,@DecryptResult标记需解密的返回值 - 在
InvocationHandler.invoke()中遍历方法参数,识别带@EncryptParam的参数,用 AES/RSA 等加密(注意:原始类型需包装,敏感字段建议用 String 或 byte[]) - 调用真实方法后,检查返回值是否标注
@DecryptResult,若是则对返回值解密 - 加密密钥建议从 Spring Environment 或配置中心获取,避免硬编码;可结合 ThreadLocal 实现加解密上下文隔离
使用 CGLIB 代理处理无接口类
当目标类无实现接口时,JDK 代理不可用,改用 CGLIB:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 继承
MethodInterceptor,重写intercept() - 通过
method.getParameterAnnotations()或参数类型(如含String且字段名含 "password"/"idCard")启发式判断是否加密 - 对匹配参数做加密(例如:手机号 138****1234 → 加密为密文字符串),再调用
obj.method(...) - 若方法返回值是敏感 DTO,且其 class 上有
@Sensitive注解,可递归对其字段解密(需配合反射+注解扫描)
加解密逻辑要避开的坑
实际落地中容易忽略但影响功能与安全的关键点:
- 不加密 null 或空字符串:避免加密后变成非法密文,解密时报错
-
跳过非业务方法:如
toString()、hashCode()、setXXX()等 setter 方法一般不参与加解密 - 保持类型一致性:加密后仍应返回原参数类型(如 String 加密后还是 String 类型密文),否则会触发 ClassCastException
- 异常处理要透出原始错误:加解密过程抛异常时,应封装为运行时异常并保留 cause,不能静默吞掉或掩盖业务异常
结合 Spring AOP 更轻量实用
比起手动写代理,Spring AOP 更适合工程化落地:
- 定义切点:
@Pointcut("@annotation(encrypt) || @annotation(decrypt)") - 在
@Around切面中解析JoinPoint的 args 和 signature,识别加解密目标 - 使用
AesUtil.encrypt(String, key)等工具类统一处理,密钥可由@Value("${security.aes.key}")注入 - 对 Controller 入参(如
@RequestBody UserDTO)可配合自定义HttpMessageConverter做全局加解密,代理只负责 Service 层细粒度控制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










