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

网友投稿 498 2023-01-31

如何动态修改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 values = (Map) 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包:

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

org.springframework.boot

spring-boot-test

org.springframework.boot

spring-boot-starter-aop

commons-lang

commons-lang

2.4

org.apache.commons

commons-lang3

commons-beanutils

commons-beanutils

<version>1.8.0

commons-collections

commons-collections

3.2.1

commons-logging

commons-logging

1.1.1

net.sf.json-lib

json-lib

2.4

二、自定义注解:

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 = "ahttp://piLog()")

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 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));

}

iFSxq // 非动态参数直接返回

return name;

}

/**

* 根据参数名返回对应的值

*

* @param map

* @param paramName

* @return

*/

public Object getValue(Map map, String paramName) {

for (Map.Entry entry : map.entrySet()) {

if (entry.getKey().equals(paramName)) {

return entry.getValue();

}

}

return null;

}

/**

* 获取方法的参数名和值

*

* @param joinPoint

* @return

*/

public Map getParams(JoinPoint joinPoint) {

Map 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:测试注解传递简单动态参数

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:解决IDEA Gradle构建报错&#39;Cause: zip END header not found&#39;
下一篇:IntelliJ IDEA创建普通的Java 项目及创建 Java 文件并运行的教程
相关文章

 发表评论

暂时没有评论,来抢沙发吧~