溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎樣動(dòng)態(tài)修改JavaBean中注解的參數(shù)值

發(fā)布時(shí)間:2021-02-19 14:07:14 來源:億速云 閱讀:397 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下怎樣動(dòng)態(tài)修改JavaBean中注解的參數(shù)值,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

我這里有一個(gè)需求需要修改Person類中的一個(gè)屬性上的注解的值進(jìn)行修改,例如:

public class Person {
 private int age;
 @ApiParam(access="lala")
 private String name;
 //get set 方法忽略 
}

將@ApiParam(access=“l(fā)ala”) 修改為@ApiParam(access=“fafa”),經(jīng)過分析是可以實(shí)現(xiàn)的,需要用到動(dòng)態(tài)代理進(jìn)行操作。

具體源碼如下所示:

@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiParam {
 String access() default "";
}

反射+動(dòng)態(tài)代理代碼如下:

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 是一個(gè)自定義的注解
 ApiParam apiParam = (ApiParam) value.getAnnotation(ApiParam.class);
 java.lang.reflect.InvocationHandler invocationHandler = Proxy.getInvocationHandler(apiParam);
 Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
 //通過反射獲取memberValues 這個(gè)屬性是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());
 //動(dòng)態(tài)代理的方式不會(huì)改變原先class文件的內(nèi)容
 }
}

補(bǔ)充:Java自定義注解并實(shí)現(xiàn)注解的偽動(dòng)態(tài)參數(shù)傳遞

自定義注解,實(shí)現(xiàn)記錄接口的調(diào)用日志,此注解可以實(shí)現(xiàn)傳遞偽動(dòng)態(tài)參數(shù)。

一、需要引入的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);
  // 獲取注解中的參數(shù)
  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);
  // 將注解中測參數(shù)值保存到數(shù)據(jù)庫,實(shí)現(xiàn)記錄接口調(diào)用日志的功能(以下內(nèi)容省略...) 
 }
 
 /**
  * 獲取注解中傳遞的動(dòng)態(tài)參數(shù)的參數(shù)值
  *
  * @param joinPoint
  * @param name
  * @return
  */
 public String getAnnotationValue(JoinPoint joinPoint, String name) {
  String paramName = name;
  // 獲取方法中所有的參數(shù)
  Map<String, Object> params = getParams(joinPoint);
  // 參數(shù)是否是動(dòng)態(tài)的:#{paramName}
  if (paramName.matches("^#\\{\\D*\\}")) {
   // 獲取參數(shù)名
   paramName = paramName.replace("#{", "").replace("}", "");
   // 是否是復(fù)雜的參數(shù)類型:對(duì)象.參數(shù)名
   if (paramName.contains(".")) {
    String[] split = paramName.split("\\.");
    // 獲取方法中對(duì)象的內(nèi)容
    Object object = getValue(params, split[0]);
    // 轉(zhuǎn)換為JsonObject
    JSONObject jsonObject = JSONObject.fromObject(object);
    // 獲取值
    Object o = jsonObject.get(split[1]);
    return String.valueOf(o);
   }
   // 簡單的動(dòng)態(tài)參數(shù)直接返回
   return String.valueOf(getValue(params, paramName));
  }
  // 非動(dòng)態(tài)參數(shù)直接返回
  return name;
 }
 
 /**
  * 根據(jù)參數(shù)名返回對(duì)應(yīng)的值
  *
  * @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;
 }
 
 /**
  * 獲取方法的參數(shù)名和值
  *
  * @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;
 } 
}

四:測試前的準(zhǔn)備內(nèi)容:

// 實(shí)體類
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層內(nèi)容
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 = "測試注解傳遞復(fù)雜動(dòng)態(tài)參數(shù)")
 public void saveUser(User user,String id){
  System.out.println("測試注解...");
 }
 
 @ApiOperationLog(resourceId = "#{id}",operationType = "UPDATE",description = "測試注解傳遞簡單動(dòng)態(tài)參數(shù)")
 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");
 }
}

測試結(jié)果:

測試注解...
resourceId:1
operationType:SAVE
description:測試注解傳遞復(fù)雜動(dòng)態(tài)參數(shù)
測試注解...
resourceId:666
operationType:UPDATE
description:測試注解傳遞簡單動(dòng)態(tài)參數(shù)

以上是“怎樣動(dòng)態(tài)修改JavaBean中注解的參數(shù)值”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI