首页 > 编程语言 >java自定义注解实现字段格式化(二)

java自定义注解实现字段格式化(二)

时间:2023-03-10 13:45:59浏览次数:62  
标签:格式化 String 自定义 java Object field obj public

上篇java自定义注解实现字段格式化 我们自定义了另一个浮点数格式化的注解

一、格式化处理器接口

但在实际生产中,处理浮点数的格式化,可能还会有其他数据的格式化,比如日期格式

这时一个对象就会面临多个*processor,我们从抽象和易扩展的角度考虑,定义一个格式化接口,

接口参数有两个,obj代表对象,field代表对象的某一个field

public interface Processor {
    void doProcess(Object obj,Field field) throws IllegalAccessException;
}

二、处理器实现类

接下来我们定义两个实现类实现上面的接口,

内容都不复杂,就是判断field上是否定义了对应的Format注解,如果有的话,按照注解上的要求对字段值进行处理。

当然在需要的时候可以再定义其他类

1.浮点数格式处理器类

@Service
public class DecimalFormatProcessor implements Processor{
    @Override
    public void doProcess(Object obj, Field field) throws IllegalAccessException {
        if (field.isAnnotationPresent(DecimalFormat.class)) {
            DecimalFormat format = field.getDeclaredAnnotation(DecimalFormat.class);
            String format1 = format.format();
            String exceptionResult = format.exception();
            field.setAccessible(true);
            Object o = field.get(obj);
            if (o!=null) {
                try {
                    double v = Double.parseDouble(o.toString());
                    String result = new Formatter().format(format1, v).toString();
                    field.set(obj,result);
                } catch (NumberFormatException e) {
                    field.set(obj,exceptionResult);
                }
            }else{
                field.set(obj,exceptionResult);
            }
        }
    }
}

2.日期格式化处理器类

@Service
@Slf4j
public class DateTimeFormatProcessor implements Processor{
    @Override
    public void doProcess(Object obj,Field field) throws IllegalAccessException {
        if (field.isAnnotationPresent(DateTimeFormat.class)) {
            DateTimeFormat format = field.getDeclaredAnnotation(DateTimeFormat.class);
            String source = format.source();
            String target = format.target();
            if(source.equals(target)){
                return;
            }
            field.setAccessible(true);
            DateTimeFormatter sourceFormat = DateTimeFormatter.ofPattern(source);
            DateTimeFormatter targetFormat = DateTimeFormatter.ofPattern(target);
            Object fieldVal = field.get(obj);
            if(fieldVal==null){
                return;
            }
            try {
                TemporalAccessor parse = sourceFormat.parse(fieldVal.toString());
                String result = targetFormat.format(parse);
                field.set(obj,result);
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }

    }
}

三、处理器工厂类

定义完实现类后,我们用一个工厂类把各种processor构造出来,在工厂中定义一个process方法

针对一个指定的对象,把这个对象中的所有属性都遍历一遍,然后调用processor类的doProcess来实际处理

@Service
public class ProcessorFactory {
    @Autowired
    private List<Processor> processorList;

    public void process(Object obj) throws IllegalAccessException {
        Class<?> aClass = obj.getClass();
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field : declaredFields) {
            for (Processor processor : processorList) {
                processor.doProcess(obj,field);
            }
        }
    }
}

四、AOP触发

此时我们在AOP中的调用的就不再是具体的处理器类,而是处理器工厂

@Slf4j
@Component
@Aspect
public class FormatAop {
    @Pointcut("@annotation(cn.jinka.gcdp.infrastructure.utils.FormatPoint)")
    public void ServiceAspect() {
    }

    @Autowired
    private ProcessorFactory processorFactory;


    @Around("ServiceAspect()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        Object[] args = proceedingJoinPoint.getArgs();
        Object proceed = null;
        try {
            proceed = proceedingJoinPoint.proceed(args);
            if(proceed instanceof List){
                List proceedList = (List) proceed;
                for (Object o : proceedList) {
                    processorFactory.process(o);
                }
            }else{
                processorFactory.process(proceed);
            }
        } catch (Throwable e) {
            log.error(e.getMessage());
        }
        return proceed;

    }
}

这样只要在对应对象的属性上定义相应的格式化注解,然后再返回对象的方法上加上切点注解,就可以生效了

//日期格式化注解
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DateTimeFormat {
     String source() default  "yyyy-MM-dd";
     String target() default "yyyy-MM-dd";
}

//浮点数格式化注解

@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DecimalFormat {
     String format() default  "%.3f";
     String exception() default "0";
}

切点注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FormatPoint {
}

切点注解使用

@FormatPoint
    public List<TestModel> test() {
        TestModel testModel = new TestModel();
        testModel.setDt("2022-03-09");
        testModel.setValue("123.4");

        TestModel testModel1 = new TestModel();
        testModel1.setDt("2022-03-10");
        testModel1.setValue("234.45678");

        return Lists.newArrayList(testModel,testModel1);
    }

 

标签:格式化,String,自定义,java,Object,field,obj,public
From: https://www.cnblogs.com/wangbin2188/p/17203047.html

相关文章