如何实现类似MyBatis @Select的Spring自定义注解并给参数Map追加数据
要实现类似MyBatis注解的自定义@CreateNode,给方法的Map参数自动追加type数据,咱们可以用自定义注解+Spring AOP的方案来搞定——这也是MyBatis等框架常用的动态代理/切面拦截思路。下面一步步来实现:
1. 完善自定义
@CreateNode注解 首先把你的CreateNode.java注解定义补全,加上必要的元注解,确保它能在运行时被读取并作用于方法:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) // 指定注解作用在方法上 @Retention(RetentionPolicy.RUNTIME) // 运行时保留注解,方便AOP逻辑读取 public @interface CreateNode { String tid(); // 定义tid属性,用来传递type字段的值 }
2. 编写AOP切面处理注解逻辑
接下来写一个切面类,拦截所有带有@CreateNode注解的方法,在方法执行前修改Map参数:
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.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.util.Map; @Aspect @Component // 把切面类交给Spring容器管理 public class CreateNodeAspect { // 定义切点:匹配所有标注了@CreateNode的方法 @Pointcut("@annotation(com.yourpackage.CreateNode)") public void createNodeMethod() {} // 前置通知:在目标方法执行前修改参数 @Before("createNodeMethod()") public void beforeCreateNode(JoinPoint joinPoint) { // 1. 获取方法上的@CreateNode注解实例 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); CreateNode createNode = signature.getMethod().getAnnotation(CreateNode.class); String typeValue = createNode.tid(); // 2. 获取方法的参数列表 Object[] args = joinPoint.getArgs(); for (Object arg : args) { // 3. 找到Map类型的参数,追加type数据 if (arg instanceof Map) { @SuppressWarnings("unchecked") Map<String, Object> dataMap = (Map<String, Object>) arg; // 直接追加type字段,如果需要避免覆盖已有值,可以先判断containsKey dataMap.put("type", typeValue); } } } }
3. 开启Spring AOP支持
如果是Spring Boot项目,只需要在启动类或者配置类上加上@EnableAspectJAutoProxy注解,让Spring启用AOP功能:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.EnableAspectJAutoProxy; @SpringBootApplication @EnableAspectJAutoProxy public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
4. 测试验证
现在你的ArtistNodeRepository接口(注意接口要被Spring代理,比如加上@Repository注解)调用create方法时,传入的Map参数会自动被追加type: artist的数据:
// 调用示例 @Autowired private ArtistNodeRepository artistNodeRepository; public void testCreateNode() throws Exception { Map<String, Object> data = new HashMap<>(); data.put("name", "Taylor Swift"); Node node = artistNodeRepository.create(data); // 此时data中会自动包含"type": "artist" System.out.println(data); // 输出: {name=Taylor Swift, type=artist} }
额外注意点
- 如果方法有多个参数,切面会遍历所有参数并修改Map类型的参数;如果需要指定特定位置的参数,可以在
@CreateNode注解里新增paramIndex属性,然后在切面中根据索引定位参数。 - 如果是非Spring项目,可以用JDK动态代理实现类似逻辑:生成接口的代理类,在
invoke方法中读取注解并修改参数。
内容的提问来源于stack exchange,提问作者Juneyoung Oh
相关产品推荐
相关产品推荐

