介绍: 在学习SpringBoot的过程中在类或属性上方添加很多注解,就可以省去很多代码功能(感觉很神奇),实际应用中知道应该添加这个注解,但是不知道其内部是如何完成的,带着这个疑问,我找了很多资料,终于想明白了,下面且听我娓娓道来!!
(一)基本介绍
从 JDK5 开始,Java增加对元数据的支持,也就是注解。简单理解就是代码里的特殊标志,这些标志可以在编译,类加载,运行时被读取,并执行相应的处理,以便于其他工具补充信息或者进行部署。
(二)内部实现机理
注解只是一个标识(它并不进行具体的操作实现),内部实现是通过反射来进行实现的哦
步骤一: 自定义注解 @MyValue @MyComponent
//指定运行期间生效
@Retention(RetentionPolicy.RUNTIME)
//表示该注解添加的对象(属性)
@Target({ElementType.FIELD})
public @interface MyValue {
//定义一个函数,用来接受数据
String value();
}
//指定运行期间生效
@Retention(RetentionPolicy.RUNTIME)
//表示该注解添加的对象(类和方法)
@Target({ElementType.TYPE,ElementType.FIELD})
public @interface MyComponent {
}
步骤二:创建实体类Dog,添加注解
/**
* 注解只是一个标识,具体操作是结合反射来进行执行的
* */
@Data
@MyComponent
public class Dog {
@MyValue("2")
private Integer age;
@MyValue("喵喵")
private String name;
}
步骤三:通过测试类来进行模拟实现过程
public class AnnotationTest {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<Dog> dogClass = Dog.class;
//获取其类是否添加了MyComponent注解(若添加则返回注解对象,反之返回null)
MyComponent annotation = dogClass.getAnnotation(MyComponent.class);
Dog dog = null;
if (annotation != null) {
//创建对象
Constructor<Dog> constructor = dogClass.getConstructor(null);
dog = constructor.newInstance(null);
//获取类中的所有属性
Field[] declaredFields = dogClass.getDeclaredFields();
for (Field declareField : declaredFields) {
MyValue valueAnnotation = declareField.getAnnotation(MyValue.class);
if (valueAnnotation != null) {
String value = valueAnnotation.value();
//暴力反射(通过反射机制强行赋值,消除对private的限制)
declareField.setAccessible(true);
//判断属性的类型(看是否需要强转)
if (declareField.getType().getName().equals("java.lang.Integer")) {
Integer val = Integer.parseInt(value);
//将值赋值给对象的id(declareField用来标识属性)
declareField.set(dog, val);
} else {
declareField.set(dog, value);
}
}
}
}
System.out.println("dog对象是: " + dog);
}
}
运行结果:
(三)优质博文推荐
优质博文一 :对注解的基本知识和使用作了详细的介绍
优质博文二 :总结了常用的注解和功能(非常全)