首页 > 其他分享 >反射、注解和反射的关系以及手写自己的注解。看完保证你能懂!

反射、注解和反射的关系以及手写自己的注解。看完保证你能懂!

时间:2024-01-06 10:35:29浏览次数:33  
标签:反射 实体类 Dog value 注解 手写 ElementType public

1.一般我们会用反射来创建对象举个例子:先创建两个实体类Dog,Cat,然后再创建一个properties配置文件如下:

bean=com.ref.Dog

在后再通过反射来动态的创建这个两个实体类的对象:

public class MyTest {
    private static Properties properties;
    static {
        try {
            properties = new Properties();
            properties.load(MyTest.class.getClassLoader().getResourceAsStream("bean.properties"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws Exception {
        //获取properties的value(类的全限定名)
        String bean = properties.getProperty("bean");
        //通过反射拿到实体类
        Class clazz = Class.forName(bean);
        //创建它的无参构造器
        Constructor constructor = clazz.getConstructor(null);
        //创建实例对象
        Object object = constructor.newInstance(null);
        System.out.println(object);
    }
}

想要创建其他实体类对象的话可以直接在properties配置文件中修改bean的value即可,达到了解耦合的效果。

一般反射除了用在创建对象上,还用在注解上。我在已经创建的Dog实体类上添加的value注解:

@Data
@Component
public class Dog {

    @Value("1")
    private Integer id;

    @Value("旺财")
    private String name;
}

然后运行打印这个实体类的实例对象:Dog(id=1,name=旺财)。然后再打开这个value注解查看:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
    String value();
}

发现什么逻辑都没有,那到底它是如何给我的实体类属性赋值的呢?注解到底是如何运行的?

注解不是单独运行,它是结合反射去运行的。意思是:注解只是一个标识,仅仅做一个标记作用,不做具体的操作,具体操作是由反射来完成的。

我们来写两个自己的注解来代替@value和@component:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValue {
    String value();
}
@Target({ElementType.TYPE})//指定是在那个目标上能用
@Retention(RetentionPolicy.RUNTIME)//配置运行的时候能生效
public @interface MyComponent {
}

并把这两个注解添加在我们的Dog实体类中:

@Data
@MyComponent
public class Dog {

    @MyValue("1")
    private Integer id;

    @MyValue("旺财")
    private String name;
}

但是此时它并不能给我们的实体类属性id,name赋值。需要通过反射机制来实现,反射启动之后,然后解析实体类Dog的信息,从而得到注解的指令,来完成赋值。具体操作如下:

public class Test {
    public static void main(String[] args) throws Exception{
        //获取Dog实体类
        Class<Dog> dogClass = Dog.class;
        //拿到Dog实体类中的MyComponent注解
        MyComponent myComponent = dogClass.getAnnotation(MyComponent.class);
        //判断Dog类中是否有MyComponent注解
        if (myComponent!=null){
            //创建对象
            Constructor<Dog> constructor = dogClass.getConstructor(null);
            Dog dog = constructor.newInstance(null);
            //开始赋值
            //获取全部的修饰符修饰的属性
            Field[] declaredFields = dogClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                //拿到属性上的MyValue注解
                MyValue valueAnnotation = declaredField.getAnnotation(MyValue.class);
                if (valueAnnotation!=null){
                    //获取注解上的value值
                    String value = valueAnnotation.value();
                    //暴力反射能给私有属性赋值
                    declaredField.setAccessible(true);
                    //判断属性的类型,如果属性是Integer则要把value转成Integer类型
                    if (declaredField.getType().getName().equals("java.lang.Integer")){
                        int val = Integer.parseInt(value);
                        declaredField.set(dog,val);
                    }else {
                        declaredField.set(dog,value);
                    }
                }
            }
            System.out.println(dog);
        } else {
            System.out.println("无法创建Dog对象");
        }
    }
}

最后执行main方法得到结果:

反射、注解和反射的关系以及手写自己的注解。看完保证你能懂!_反射

所以注解是依靠反射来实现的。

标签:反射,实体类,Dog,value,注解,手写,ElementType,public
From: https://blog.51cto.com/u_16376975/9125135

相关文章

  • springMVC的常见注解,以及注解的作用。@Controller,@RestController,@RequestMapping,@
    目录注:使用注解,必须要开启注解包扫描1.@Controller2.@RequestMapping3.@PathVariable4.@RequestParam5.@RequestHeader6.@CookieValue7.@RequestBody该注解的作用8.@ResponseBody9.@RestController注:使用注解,必须要开启注解包扫描在MVC核心配置中开启注解包扫描<!--  配置包......
  • 反射
    【一】反射【1】什么是反射反射是一种程序可以访问、检测和修改其本身状态或行为的能力。在Python中,反射主要指通过字符串的形式操作对象的属性。【2】Python中的反射通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)【二】反射方法......
  • springmvc的五个常用注解?
    1、@Controller在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在SpringMVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特......
  • 反射
    反射在Python中,反射是指在运行时获取对象的信息,包括对象的属性和方法,以及动态地操作这些属性和方法。在面向对象编程中,反射允许你在运行时检查类和对象的信息,而不是在编写代码时硬编码这些信息。(1)获取对象属性值和方法/调用getattr()使用getattr()函数可以获取对象的属......
  • Spring学习记录之手写Spring框架
    Spring学习记录之手写Spring框架前言这篇文章是我第二次学习b站老杜的spring相关课程所进行的学习记录,算是对课程内容及笔记的二次整理,以自己的理解方式进行二次记录,其中理解可能存在错误,欢迎且接受各位大佬们的批评指正;关于本笔记,只是我对于相关知识遗忘时快速查阅了解使用,至......
  • python面向对象之派生、组合、抽象类、反射
    【派生】在子类派生的新方法中如何重用父类的功能?  【组合】(定义) (案例) (组合和继承的区别) 【抽象类】(定义) (案例) 实例化 (总结) 【反射】什么是反射 如何反射 实现反射机制的步骤 解决办法 ......
  • Java 自定义注解
    1. 元注解元注解是Java 提供的一些基本注解,使用这些元注解区可疑创建新的注解;可以先大致看一下元注解,然后去看后面自定义注解的例子。元注解有@Retention,@Documented,@Target,@Inherited,@Repeatable 五种。1.1 @Retention@Retention 可以定义注解的生命周期,注解的存活时......
  • 手写topN算法-c语言
    #include<stdio.h>#include<malloc.h>structTreeHeap{intv;};typedefstructTreeHeapTreeHeap;staticvoidprint_bp(intbp[],intlen);voidcreate_treeheap(TreeHeap*treeheap,intdata[10],intbp[11]){treeheap->v=1;......
  • java 注解中 必填值
    Java注解中的必填值引言在Java编程中,注解(Annotation)是一种用于向代码中添加元数据的方式。它们提供了一种在代码中添加说明、配置和约束的方法。在使用注解时,有时候需要指定一些必填值,以确保注解的正确使用。本文将介绍Java注解中必填值的概念,并使用代码示例进行说明。什么是必......
  • java 注解默认参数
    Java注解默认参数实现流程引言本文将介绍如何在Java中实现注解的默认参数。注解是Java中一种元数据的形式,可以用来描述类、方法、字段等。通过给注解添加默认参数,可以在使用注解时不需要指定所有参数的值,从而简化代码编写。总体流程下面是实现Java注解默认参数的整体流程:flowc......