我是靠谱客的博主 哭泣战斗机,最近开发中收集的这篇文章主要介绍通过 Spring AOP + 自定义注解 + 反射 的方式,完成值集转换,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言:

     本次通过AOP + 自定义注解 + 反射,完成实际项目中值集转换成名称的操作。

目的:

     在Java Bean 中,给某个值集字段,增加一个注解后,返回给前台的结果 Json 中,自动将 code编码 转换成 code编码中文名称

思路:

      1. 自定义一个注解;

      2. 通过AOP中的 @AfterReturning,在返回值被返回前进行数据处理;

      3. 通过反射拿到类中的所有字段,判断字段上是否有自定义注解,如果有,则进行值集转换处理。

代码位置:

      https://gitee.com/jin_0611/java-custom-annotation

下面只展示部分代码,所有的代码都放在了gitee中,有需要可以实际运行一下,加以改造,可以投入到实际项目中。

自定义注解涉及的知识点,请参考:https://blog.csdn.net/zt15732625878/article/details/100061528

1. 自定义一个注解;

package com.duzq.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 值集转换注解
*
* 使用该注解的Bean对象需要继承 com.duzq.common.entity.BaseEntity
* @author duzq
* @date 2021-03-24 14:51:45
*/
// @Target,注解应用的范围(注解可以写到什么地方)
// ElementType.FIELD,应用与属性上(Java Bean的字段,例如:private String name;)
@Target(ElementType.FIELD)
// @Retention,注解的生命周期(什么时候有效)
// RetentionPolicy.RUNTIME,代码编译后可以看到,class文件在JVM中的时候也可以被看到
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumValue {
/**
* 枚举
*/
String enumType() default "";
/**
* 将转换后的值赋值到哪个变量上面
* 不传入值,使用添加了该注解的字段后面拼接 xxxName
*/
String targetField() default "";
}

 2. 通过AOP中的 @AfterReturning,在返回值被返回前进行数据处理;

 3. 通过反射拿到类中的所有字段,判断字段上是否有自定义注解,如果有,则进行值集转换处理。

package com.duzq.common.aop;
import com.duzq.common.annotation.EnumValue;
import com.duzq.common.entity.BaseEntity;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
/**
* 值集转换注解 aop
*
* @author duzq
* @date 2021-03-24 14:51:45
*/
@Component
@Aspect
public class EnumValueAspect {
/**
* 在返回之前进行拦截
*/
@AfterReturning(value = "execution(* com.duzq.controller..*.*(..))", returning = "result")
public Object enumValue(Object result) {
// 空返回直接返回
if (Objects.isNull(result)) {
return null;
}
// list,特殊处理一下
if (result instanceof List) {
List list = (List) result;
for (Object o : list) {
setEnumValue(o, o.getClass());
}
return result;
}
// 项目中单个的自定义Bean对象,进行处理
setEnumValue(result, result.getClass());
return result;
}
/**
* 开始根据注解,转换值
*
* @param result
*/
private void setEnumValue(Object result, Class clazz) {
// 不是自己项目中的 bean 直接返回
if (!(result instanceof BaseEntity)) {
return;
}
// 如果当前的类是 BaseEntity,则不执行后续操作
if (BaseEntity.class.getName().equals(result.getClass().getName())) {
return;
}
// 1. 获取当前对象的所有字段
Field[] fields = clazz.getDeclaredFields();
if (fields == null || fields.length == 0) {
return;
}
// 2. 遍历字段上是否有自定义注解
for (Field field : fields) {
try {
EnumValue annotation = field.getAnnotation(EnumValue.class);
if (annotation == null) {
continue;
}
if (Objects.isNull(annotation.enumType())) {
continue;
}
// 通过设置可以访问私有变量的值
field.setAccessible(true);
if (Objects.isNull(field.get(result))) {
continue;
}
// 获取跟CODE编码的名称
String codeName = getCodeName(annotation.enumType(), field.get(result));
if (Objects.isNull(codeName)) {
continue;
}
// 编辑set方法名称
String setMethodName = null;
if (!"".equals(annotation.targetField())) {
setMethodName = "set" +
annotation.targetField().substring(0, 1).toUpperCase() +
annotation.targetField().substring(1);
} else {
setMethodName = "set" +
field.getName().substring(0, 1).toUpperCase() +
field.getName().substring(1) +
"Name";
}
// 执行set方法
Method method = result.getClass().getMethod(setMethodName, String.class);
if (Objects.isNull(method)) {
continue;
}
method.invoke(result, codeName);
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
// 递归获取父类的属性
setEnumValue(result, clazz.getSuperclass());
}
/**
* 获取跟CODE编码的名称
*
* @param enumType
* @param code
* @return
*/
private String getCodeName(String enumType, Object code) {
// TODO: 查询缓存、或者查询数据库,每个项目不一致,需要维护成自己项目中的代码
// TODO: 只是为了梳理自定义注解使用的场景,返回值写了固定值。
return "查询缓存、或者查询数据库";
}
}

 

最后

以上就是哭泣战斗机为你收集整理的通过 Spring AOP + 自定义注解 + 反射 的方式,完成值集转换的全部内容,希望文章能够帮你解决通过 Spring AOP + 自定义注解 + 反射 的方式,完成值集转换所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部