小编给大家分享一下怎样动态修改JavaBean中注解的参数值,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!
我这里有一个需求需要修改Person类中的一个属性上的注解的值进行修改,例如:
public class Person { private int age; @ApiParam(access="lala") private String name; //get set 方法忽略 }
将@ApiParam(access=“lala”) 修改为@ApiParam(access=“fafa”),经过分析是可以实现的,需要用到动态代理进行操作。
具体源码如下所示:
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface ApiParam { String access() default "";}
反射+动态代理代码如下:
public class TestClazz { public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { Person person = new Person(); Field value = person.getClass().getDeclaredField("name"); value.setAccessible(true); //APIParam 是一个自定义的注解 ApiParam apiParam = (ApiParam) value.getAnnotation(ApiParam.class); java.lang.reflect.InvocationHandler invocationHandler = Proxy.getInvocationHandler(apiParam); Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues"); //通过反射获取memberValues 这个属性是Map类型 存放着所有的属性。 memberValues.setAccessible(true); Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler); String val = (String) values.get("access"); System.out.println("------改之前:"+val); values.put("access", "fafa");//修改属性 System.out.println("-----------------"); //Field value1 = person.getClass().getDeclaredField("name"); value.setAccessible(true); ApiParam apiParam1 = (ApiParam) value.getAnnotation(ApiParam.class); System.out.println("------改之后:"+apiParam1.access()); //动态代理的方式不会改变原先class文件的内容 }}
补充:Java自定义注解并实现注解的伪动态参数传递
自定义注解,实现记录接口的调用日志,此注解可以实现传递伪动态参数。
一、需要引入的jar包:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency><!-- test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency><!-- json --> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.8.0</version> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> </dependency> </dependencies>
二、自定义注解:
package com.example.demo.annotation; import java.lang.annotation.*; @Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface ApiOperationLog { String resourceId() default ""; String operationType(); String description() default "";}
三、定义切面:
package com.example.demo.aspect; import com.example.demo.annotation.ApiOperationLog;import net.sf.json.JSONObject;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.stereotype.Component; import java.util.HashMap;import java.util.Map; @Aspect@Componentpublic class ApiOperationAspect { @Pointcut("@annotation ( com.example.demo.annotation.ApiOperationLog)") public void apiLog() { } @AfterReturning(pointcut = "apiLog()") public void recordLog(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 获取方法上的指定注解 ApiOperationLog annotation = signature.getMethod().getAnnotation(ApiOperationLog.class); // 获取注解中的参数 String resourceId = getAnnotationValue(joinPoint, annotation.resourceId()); String operationType = getAnnotationValue(joinPoint, annotation.operationType()); String description = getAnnotationValue(joinPoint, annotation.description()); System.out.println("resourceId:" + resourceId); System.out.println("operationType:" + operationType); System.out.println("description:" + description); // 将注解中测参数值保存到数据库,实现记录接口调用日志的功能(以下内容省略...) } public String getAnnotationValue(JoinPoint joinPoint, String name) { String paramName = name; // 获取方法中所有的参数 Map<String, Object> params = getParams(joinPoint); // 参数是否是动态的:#{paramName} if (paramName.matches("^#\\{\\D*\\}")) { // 获取参数名 paramName = paramName.replace("#{", "").replace("}", ""); // 是否是复杂的参数类型:对象.参数名 if (paramName.contains(".")) { String[] split = paramName.split("\\."); // 获取方法中对象的内容 Object object = getValue(params, split[0]); // 转换为JsonObject JSONObject jsonObject = JSONObject.fromObject(object); // 获取值 Object o = jsonObject.get(split[1]); return String.valueOf(o); } // 简单的动态参数直接返回 return String.valueOf(getValue(params, paramName)); } // 非动态参数直接返回 return name; } public Object getValue(Map<String, Object> map, String paramName) { for (Map.Entry<String, Object> entry : map.entrySet()) { if (entry.getKey().equals(paramName)) { return entry.getValue(); } } return null; } public Map<String, Object> getParams(JoinPoint joinPoint) { Map<String, Object> params = new HashMap<>(8); Object[] args = joinPoint.getArgs(); MethodSignature signature = (MethodSignature) joinPoint.getSignature(); String[] names = signature.getParameterNames(); for (int i = 0; i < args.length; i++) { params.put(names[i], args[i]); } return params; } }
四:测试前的准备内容:
// 实体类package com.example.demo.model; public class User { private Long id; private String name; private int age; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; }} // controller层内容package com.example.demo.controller; import com.example.demo.annotation.ApiOperationLog;import com.example.demo.model.User;import org.springframework.web.bind.annotation.RestController; @RestControllerpublic class LoginController { @ApiOperationLog(resourceId = "#{user.id}",operationType = "SAVE",description = "测试注解传递复杂动态参数") public void saveUser(User user,String id){ System.out.println("测试注解..."); } @ApiOperationLog(resourceId = "#{id}",operationType = "UPDATE",description = "测试注解传递简单动态参数") public void updateUser(User user,String id){ System.out.println("测试注解..."); } }
五、测试类:
package com.example.demo.aspect; import com.example.demo.DemoApplication;import com.example.demo.controller.LoginController;import com.example.demo.model.User;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class)@SpringBootTest(classes = DemoApplication.class)public class ControllerTest { @Autowired private LoginController loginController; @Test public void test(){ User user = new User(); user.setId(1L); user.setName("test"); user.setAge(20); loginController.saveUser(user,"123"); loginController.updateUser(user,"666"); }}
测试结果:
测试注解...resourceId:1operationType:SAVEdescription:测试注解传递复杂动态参数测试注解...resourceId:666operationType:UPDATEdescription:测试注解传递简单动态参数
以上是“怎样动态修改JavaBean中注解的参数值”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!