您现在的位置是:首页 >技术杂谈 >通过注解获取和改变Bean的某变量值网站首页技术杂谈
通过注解获取和改变Bean的某变量值
简介通过注解获取和改变Bean的某变量值
Java有时需要通过自定义注解,获取某Bean的某变量的值,根据业务要求处理数据,然后再把新值设置回Bean的同一变量中,下面我们简要介绍一下,如何实现,
1,自定义注解的定义
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 注解的作用范围,必用,
// 如用在类上,方法上,属性上等,更多参考ElementType枚举
@Target(ElementType.FIELD)
// 注解的生命周期,即注解的保留时间阶段,必用,
// SOURCE,表示该注解的生命周期只在编译阶段,
// CLASS,该注解被保留在class文件上
// RUNTIME,该注解生命周期在运行时
@Retention(RetentionPolicy.RUNTIME)
// 是一个标记注解,没有定义属性,作用是为了表示该注解可以被继承,非必用
// 使用了该元注解的自定义注解,应用到某父类上,则该类的子类也默认继承了该注解
// @Inherited
// 是一个标记注解,里面没有任何属性,非必用
// 用 @Documented 注解修饰的注解类会被 JavaDoc 工具提取成文档
// @Documented
// 允许在目标对象重复使用该注解, 指定重复类,仅参考暂不用,非必用
// @Repeatable(BeanFieldChecks.class)
public @interface BeanFieldCheck {
/** 校验结果信息*/
String message()'
/** 校验器*/
Class validator();
}
// 仅提供参考,不使用
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BeanFieldChecks {
/** 注解复数,即同一变量可以多次使用同一注解,
可以不使用,单个注解已可以完成事情 */
BeanFieldCheck[] values();
}
2,注解在Bean中的使用
public class User {
@ApiModelProperty(value="主键ID")
private Long id;
// 注解使用
@ApiModelProperty(value="用户编码")
@JavaField(message="编码不能为空", validator=UserValidator01.class)
private String userCode;
// 注解使用
@ApiModelProperty(value="用户名称")
@JavaField(message="姓名不能含特殊字符和重名", validator=UserValidator02.class)
private String userName;
@ApiModelProperty(value="年龄")
private Interger age;
// ...getter/setter省略
}
3,注解的业务处理逻辑
根据注解要求获取Bean某变量的值,按业务要求处理,之后把新值赋给原变量,以 UserValidator02.java 为例子:
public class UserValidator02 {
// 方法功能:根据Bean的变量注解,获取类变量的原值,
// 再根据注解数据处理,重新赋给原来的变量
public static <T> T updateModelValue(T bean) {
if (null == bean) {
return null;
}
// 获取目标model的java类
Class cls = bean.getClass();
// 获取类的所有字段变量
Field[] fields = cls.getDeclareFields();
for (Field field : fields) {
// 获取某个类型的注解为:
//Annotation an = field.getAnnotation(BeanFieldCheck.class)
// 获取字段的全部注解
Annotation ans = field.getAnnotations();
if (null == ans || ans.length < 1) {
continue;
}
// 遍历X字段上的所有注解
for (Annotation an : ans) {
if (null == an) {
continue;
}
// 对象的变量名, 不做它用,仅显示用法
String fieldName = field.getName();
// 获取指定类型注解内message的值
String tempVal = "";
if (an instanceof BeanFieldCheck) {
// 获取Bean类变量的该类型注解中message配置项值
BeanFieldCheck anItem = (BeanFieldCheck)an;
tempVal = anItem.message();
}
try {
// 类变量是private私有,需改变为可访问性
field.setAccessible(true);
//获取类变量的原来值
Object oldVal = field.get(bean);
// 这里可根据自己业务要求处理数据,此处仅简单暂时
if (null != oldVal) {
tempVal = oldVal.toString() + "," + tempVal;
}
// 将新值赋回类变量的该字段中
field.set(bean, tempVal);
// 恢复变量private特性
field.setAccessible(false);
} catch(Exception e) {
e.printStackTrace();
}
}
}
//返回修改类变量后的Bean
return bean;
}
// 其它方法省略
}
4,如何触发执行注解的业务逻辑
上面定义了自定义的注解,校验器逻辑,以及注解的使用,但怎么触发没有,
可以通过代码主动调用触发,例如:
User newUser = UserValidator02.updateModelValue(user);
还可以更好一点,推荐定义一个AOP切面,让使用了 BeanFieldCheck 注解的地方在切面中自动触发进行校验处理,AOP切面不在本中展开,简要提供如下:
@Component //使该类被springIOC扫描到,交由spring管理
@Aspect //定义为aop切面类
public class UserCheckAspect {
// 定义方法作用的目标表达式
@Pointcut(value="@annotation(com.aa.bb.cc.BeanFieldCheck")
public void myPointcut01(){}
// 根据需要定义和修改
@Pointcut(value = "execution(* com.aa.bb.cc.BeanFieldCheck..*(..))")
public void myPointcut02(){}
@Before(value="myPointcut01()")
public void beforeExecute(JoinPoint joinPoint){
// 调用UserValidator02.updateModelValue()处理
//TODO...方法执行前的逻辑处理...
}
@Around(value="myPonitcut01()")
public void aroundExecute(ProceedingJoinPoint joinPoint) throws Throwable{
// 调用UserValidator02.updateModelValue()处理
//TODO...方法执行前后的逻辑处理...
}
@After(value="myPonitcut01()")
public void afterExecute(JoinPoint joinPoint) throws Throwable{
// 调用UserValidator02.updateModelValue()处理
//TODO...方法执行后的处理...
}
}
以上展示了,自定义注解的写法,应用,以及如何通过注解对Java的Bean中某个变量的获取原值,数据处理,赋给原来变量的方法和过程,在实际使用根据自己需要相应的修改,欢迎拍砖讨论...
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。