软件编程
位置:首页>> 软件编程>> java编程>> 如何动态修改JavaBean中注解的参数值

如何动态修改JavaBean中注解的参数值

作者:消魂钉  发布时间:2022-09-03 04:08:34 

标签: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)
@Documented
public @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
@Component
public 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);
 // 将注解中测参数值保存到数据库,实现记录接口调用日志的功能(以下内容省略...)
}

/**
 * 获取注解中传递的动态参数的参数值
 *
 * @param joinPoint
 * @param name
 * @return
 */
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;
}

/**
 * 根据参数名返回对应的值
 *
 * @param map
 * @param paramName
 * @return
 */
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;
}

/**
 * 获取方法的参数名和值
 *
 * @param joinPoint
 * @return
 */
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;
@RestController
public 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:1
operationType:SAVE
description:测试注解传递复杂动态参数
测试注解...
resourceId:666
operationType:UPDATE
description:测试注解传递简单动态参数

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

来源:https://blog.csdn.net/ltllml44/article/details/84305262

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com