Spring实现数据字典翻译

在开始之前,首先我们要了解一个类:BeanPropertyWriter。
这个类是由SerializerFactory 工厂进行实例化的,其作用是对bean中的每个字段进行jackson操作的封装,其中封装了字段的一些元信息,和对此字段进行jackson序列化的操作。
采用Spring项目进行Web服务开发时,在获取到数据后,Spring会通过BeanPropertyWriter对数据进行jackson封装,将其转换为Json串。
如果我们需要在不影响逻辑的情况下对数据进行字典翻译,重写此类是较好的选择

字典翻译实现步骤:
1.实现获取字典的接口 read more

Java使用SpringBoot应用配置文件

*配置文件yml和properties均可,以下以yml为例
1.设置配置文件
app:
service:
name: justin
id: 000
2.创建配置文件映射类

@Component//如报错请将此注解注释,因为此时出现了该bean被注册两次的情况
@ConfigurationProperties("app.service")
public class ServiceProperties {

    private String name;//注意该字段名要与配置文件中保持一致
    private String id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

3.创建配置文件读取类并将值赋给对应服务 read more

自定义Java注解

注解的作用:

1.生成文档
这是最常见的,也是java 最早提供的注解。常用的有 @see @param @return 等

2.跟踪代码依赖性,实现替代配置文件功能
Spring中大量运用注解来简化配置文件

3.在编译时进行格式检查

如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出

实现一个简单的注解:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyTarget {
}
上面是一个最简单的注解实现,没有定义任何的属性
需要注意的是@Retention(RetentionPolicy.RUNTIME)是定义注解所必须的。
 
@Retention是注解的注解,称为注解的元注解。
括号里有一个枚举类型的值,即为注解内部定义的值。打开Retention的实现:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}
可以看到这里定义了一个变量value并且没有缺省值,所以不写这个value就会报错。 
继续打开RetentionPolicy:
public enum RetentionPolicy {
    SOURCE,
    CLASS,
    RUNTIME
}
可以发现这个枚举类定义了三个值,这三个值分别代表的是我们定义的MyTarget如何保持。

@Retention(RetentionPolicy.CLASS)
注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候

@Retention(RetentionPolicy.SOURCE)
注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中

@Retention(RetentionPolicy.RUNTIME)
注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时

还需要注意的是java的元注解一共有四个: 
@Document 
@Target 
@Retention 
@Inherited

各个的作用,读者自己查一下吧。

注解处理的一个基础:
 T getAnnotation(Class annotationClass): 
返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。

Annotation[] getAnnotations():
返回该程序元素上存在的所有注解。

boolean is AnnotationPresent(Class annotationClass):
判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.

Annotation[] getDeclaredAnnotations():
返回直接存在于此元素上的所有注释。
与此接口中的其他方法不同,该方法将忽略继承的注释。
(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)
该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

实现为属性赋值的注解:
package com.justin.test.util;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface CarNameTarget {
    String name() default "";
}
package com.justin.test.util;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface CarSalerTarget {
    String salerName();

    int age() default 1;
}
package com.justin.test.entity;

import com.justin.test.util.CarNameTarget;
import com.justin.test.util.CarSalerTarget;

/**
 * 描述:
 * 汽车实体类
 *
 * @author 孫兵
 * @create 2018-05-15 10:16
 */
public class BnechCar {
    @CarNameTarget(name = "奔驰")
    private String name;

    @CarSalerTarget(salerName = "justin", age = 22)
    private String salerInfo;
}
package com.justin.test.util;

import java.lang.reflect.Field;

/**
 * 描述:
 * 汽车信息工具类
 *
 * @author 孫兵
 * @create 2018-05-15 10:19
 */
public class CarInfoUtil {

    public static void getFruitInfo(Class<?> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(CarNameTarget.class)) {
                CarNameTarget carNameTarget = field.getAnnotation(CarNameTarget.class);
                String carColour = "汽车的中文名:" + carNameTarget.name();
                System.out.println(carColour);
            } else if (field.isAnnotationPresent(CarSalerTarget.class)) {
                CarSalerTarget carSalerTarget = field.getAnnotation(CarSalerTarget.class);
                String salerInfo = "销售员姓名:" + carSalerTarget.salerName() + ",年龄:" + carSalerTarget.age();
                System.out.println(salerInfo);
            }
        }
    }
}
/**
     * 自定义注解测试
     */
    private void targetTest() {
        CarInfoUtil.getFruitInfo(BnechCar.class);
    }

打印信息:

汽车的中文名:奔驰
销售员姓名:justin,年龄:22