aop+反射:ログカット(listおよびその他のタイプの値を取得)
1:役割
1.取得方法のあるパラメータの属性の値(戻り値タイプは不確定で、必要なパラメータはオブジェクト内の位置が不確定)
2:例を挙げる
需要:操作ログを記録し、ユーザーが注文を削除したり、物品を購入したりする操作を保存する。
2.1:コメント
2.3のdelOrdersメソッドのidsとremarkを取得しても、buyGoodsのordedersIdを取得します。
3:うどん
ここでは汎型を使いますが、受信パラメータの値は共通です。
長所反射により、任意のオブジェクトの属性値を取得することができます。属性の位置がどんなに深いかにかかわらず、(エルゴードによって取得された値:ordented-indsによって、idsの値を取得します。) 汎型を使用して、値を取得する結果のタイプは、実際の状況に応じて変化することができます。(1)。(1)中間層であれば、 をさらに処理する必要があります。
3.重点方法(いずれも汎型を使う)
パラメータに対応する値を取得する
1.取得方法のあるパラメータの属性の値(戻り値タイプは不確定で、必要なパラメータはオブジェクト内の位置が不確定)
2:例を挙げる
需要:操作ログを記録し、ユーザーが注文を削除したり、物品を購入したりする操作を保存する。
2.1:コメント
/**
*
* @Auther: ZhangSuchao
* @Date: 2020/7/29 21:02
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SaveLog {
// ( ) id
String idsName() default "";
//
int operatorKind() default 0;
// ( , )
String remarkName() default "";
}
2.2:要求エンティティ類import lombok.Data;
/**
* @Auther: ZhangSuchao
* @Date: 2020/7/29 20:02
*/
@Data
public class OrderDTO {
// s
private Integer ids;
//
private String remark;
}
2.3:サービスの方法 /**
*
*
* @param orderDTO
*/
@SaveLog(idsName = "orderDTO-ids", remarkName = "orderDTO-remark", operatorKind = 1)
public void delOrders(OrderDTO orderDTO) {
// TODO: 2020/7/29
}
/**
*
*
* @param orderId id
*/
@SaveLog(idsName = "orderId", operatorKind = 2)
public void buyGoods(Integer orderId) {
// TODO: 2020/7/29
}
2.4:目的2.3のdelOrdersメソッドのidsとremarkを取得しても、buyGoodsのordedersIdを取得します。
3:うどん
/**
*
*
* @Auther: ZhangSuchao
* @Date: 2020/7/29 19:38
*/
@Aspect
@Component
public class LogAspect {
@Pointcut(value = "@annotation(com.draymond.aop.annotation.SaveLog)")
public void logPoint() {
}
@AfterReturning(value = "logPoint()")
public void saveLog(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SaveLog saveLog = method.getAnnotation(SaveLog.class);
if (saveLog == null) {
return;
}
//
String[] paraNames = signature.getParameterNames();
//
Object[] paraValues = joinPoint.getArgs();
// :idsName Integer, List
String idsName = saveLog.idsName();
int operatorKind = saveLog.operatorKind();
String remarkName = saveLog.remarkName();
// Integer/List : idsName , ( )
Object object = ReflectUtils.getValueByParaName(idsName, paraNames, paraValues);
// String
String remark = ReflectUtils.getValueByParaName(idsName, paraNames, paraValues);
//
List idsList = ReflectUtils.parse2IntList(object);
// todo
}
}
4:反射工具類ここでは汎型を使いますが、受信パラメータの値は共通です。
package com.draymond.aop.spring.aspect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
*
*
* @Auther: ZhangSuchao
* @Date: 2020/7/29 20:18
*/
public class ReflectUtils {
/**
* idsName paraValues
*
* @param paraName
* @param paraNames
* @param paraValues
* @param
* @return
*/
public static T getValueByParaName(String paraName, String[] paraNames, Object[] paraValues) {
String[] paraNameSplit = paraName.split("-");
int paraNameLength = paraNameSplit.length;
if (paraNameSplit.length == 0) {
return null;
}
// (orderDTO-ids orderDTO )
int index = ReflectUtils.getIndex(paraNameSplit[0], paraNames);
if (index < 0) {
return null;
}
Object object = ReflectUtils.getValue(index, paraValues);
Object tempObj = object;
try {
for (int i = 0; i < paraNameLength - 1; i++) {
Class> clz = object.getClass();
Field paraField = clz.getDeclaredField(paraNameSplit[i + 1]);
paraField.setAccessible(true);
// Integet String...
if (Integer.class.isAssignableFrom(paraField.getType()) || String.class.isAssignableFrom(paraField.getType())) {
tempObj = paraField.get(object);
}
//
else if (List.class.isAssignableFrom(paraField.getType())) {
tempObj = ReflectUtils.getList(paraField, tempObj);
}
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return (T) tempObj;
}
/**
* list
*
* @param paraField
* @param tempObj
* @param
* @return
*/
/**
* list
*
* @param object
*/
public static List getList(Field field, Object object) {
List resultList = new ArrayList<>();
if (object != null) {
try {
Class clzz = field.get(object).getClass();
// list size
Method sizeMethod = clzz.getDeclaredMethod("size");
if (!sizeMethod.isAccessible()) {
sizeMethod.setAccessible(true);
}
//
int size = (int) sizeMethod.invoke(field.get(object));
//
for (int i = 0; i < size; i++) {
// list get
Method getMethod = clzz.getDeclaredMethod("get", int.class);
// get
if (!getMethod.isAccessible()) {
getMethod.setAccessible(true);
}
Object invoke = getMethod.invoke(field.get(object), i);
T var1 = (T) invoke;
resultList.add(var1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return resultList;
}
/**
*
*
* @param index
* @param paraValues
* @return
*/
private static Object getValue(int index, Object[] paraValues) {
return (index >= 0 && paraValues.length > index) ? paraValues[index] : null;
}
/**
* paraName paraNames
*
* @param paraName
* @param paraNames
* @return
*/
private static int getIndex(String paraName, String[] paraNames) {
for (int i = 0; i < paraNames.length; i++) {
if (paraName.equals(paraNames[i])) {
return i;
}
}
return -1;
}
/**
* object List
*
* @param object
* @return
*/
public static List parse2IntList(Object object) {
List list = new ArrayList<>();
if (object instanceof Integer) {
list.add((Integer) object);
} else if (object instanceof List) {
// object List
list = (List) object;
}
return list;
}
}
湖南省の備考:長所
3.重点方法(いずれも汎型を使う)
パラメータに対応する値を取得する
public static T getValueByParaName(String paraName, String[] paraNames, Object[] paraValues)
は、リストpublic static List getList(Field field, Object object)
を取得する。