Java 切面与反射问题总结
·
Java 切面与反射问题总结
1. 切面类为什么要用反射给对象赋值
问题背景:
你在 AutoFillAspect 切面中,需要在数据库插入/更新前给实体对象的公共字段(如 createTime、updateTime、createUser、updateUser)赋值。
原因分析:
-
切面操作的是未知类型对象
Object entity = joinPoint.getArgs()[0];entity的具体类型在编译期未知(可能是User、Category等)。- 编译器无法直接调用
entity.setCreateTime(...)。
-
反射允许在运行时动态调用方法
Method setCreateTime = entity.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class); setCreateTime.invoke(entity, LocalDateTime.now());- 无需知道对象具体类型,只要有对应方法就能调用。
- 实现了切面通用逻辑,无需修改每个实体类。
-
可选方案
-
如果所有实体类实现统一接口或继承父类,可以直接调用方法,避免反射:
AutoFillEntity entity = (AutoFillEntity) args[0]; entity.setCreateTime(now); -
反射的优点是无需改动现有实体类,缺点是性能略低。
-
2. 什么时候用反射
适用场景:
-
运行时类型未知,需要动态调用方法或访问字段
- 如切面中对任意实体对象赋值公共字段。
-
动态创建对象实例
Class<?> clazz = Class.forName("com.example.User"); Object obj = clazz.getDeclaredConstructor().newInstance(); -
框架或工具开发
- Spring IoC / DI 自动注入 Bean
- MyBatis / JPA 动态 SQL 映射
- JSON 序列化/反序列化工具
- 测试工具调用私有方法或字段
不适用场景:
- 对象类型已知,直接调用方法即可
- 性能敏感的代码路径
- 安全要求严格的场景
总结:
反射用于处理编译期未知类型或方法,实现通用逻辑,但不适合普通业务逻辑。
3. 切面中用反射的核心原因
- 切面拦截的是通用 Mapper 方法,参数类型不确定。
- 反射可以在运行时动态获取对象的类信息并调用方法。
- 允许统一处理“自动填充字段”,无需修改所有实体类。
可选替代方案:
- 定义统一接口或父类,但改动成本高。
- 反射的优势是通用性强,无侵入现有代码结构。
更多推荐
所有评论(0)