上篇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