【反射】注解的底层实现

Java中的反射(Reflection)是一种强大的工具,它允许在运行时检查和修改程序的行为。反射机制使得Java程序能够在运行时分析类、接口、字段和方法的信息。这种能力在实际应用中非常有用,例如开发框架、工具、插件等。

通过反射,Java代码可以获取类的所有信息(如名称、成员变量、成员方法、构造函数等),并且可以动态地创建对象、调用方法和改变字段值。这使得开发人员可以在不知道具体类名称的情况下,编写出能够操作这些类的代码。

Java反射应用场景的逐一举例:

  1. 框架设计:
    在框架设计中,反射被广泛用于实现依赖注入和控制反转。例如,在Spring框架中,可以使用反射来创建和管理bean。Spring通过反射扫描类路径,自动识别并注册bean,并根据配置文件或注解来注入依赖。这样,开发人员就可以专注于编写业务逻辑,而不用手动管理对象的创建和依赖关系。

  2. 插件可扩展性:
    插件可扩展性是通过反射实现动态加载和扩展功能的一种方式。例如,开发一个扩展性强的应用程序时,可以使用反射来加载插件JAR包中的类,并通过反射调用插件提供的方法。这样,其他开发人员可以编写符合一定规范的插件,并将其集成到应用程序中,以扩展应用程序的功能,而无需修改源代码。

  3. 单元测试:
    在单元测试中,反射可用于访问和操作私有字段和方法,以便进行测试。例如,使用反射可以修改一个私有字段的值,以便测试一个特定条件下的代码分支。或者,可以使用反射调用一个私有方法,以确保该方法的行为符合预期。这样的测试能够更全面地覆盖代码,并提高代码质量。

  4. 序列化与反序列化:
    在对象序列化和反序列化的过程中,反射起着重要作用。例如,使用Jackson库将Java对象转换为JSON字符串时,Jackson会利用反射获取对象的类信息,并将其转换为相应的JSON表示。同样地,在将JSON字符串反序列化为Java对象时,Jackson会使用反射根据JSON数据的结构和类型信息创建相应的对象实例,并设置其属性值。

这些举例展示了Java反射在不同应用场景中的使用方式。通过反射,Java能够在运行时动态地获取和操作类、方法、字段等信息,从而实现更加灵活、可扩展和可测试的代码。

反射的优点:

  • 灵活性:反射提高了Java的灵活性,可以在运行时动态地获取类的信息并调用其方法,而无需硬编码。
  • 可扩展性:通过反射可以加载外部的类和方法,增强了代码的可扩展性。

反射的缺点:

  • 性能开销:反射涉及动态解析类的信息,这在性能上比直接的Java代码要慢得多。
  • 安全性问题:由于反射可以访问私有方法和字段,它可能会破坏封装性,导致代码的安全性问题。
  • 代码可读性:大量使用反射会使得代码难以理解和维护,因为它违反了面向对象编程的一些基本原则。
  • 依赖问题:过度使用反射可能导致紧密的依赖关系,使得代码难以测试和复用。

因此,在使用反射时,需要权衡其灵活性和带来的性能、安全性问题。尽量避免在性能敏感的场合下大量使用反射,同时要注意保证代码的安全性和可读性。

//反射的几大作用
//1. 识别注解 最重要(框架的底层)
//2.1. 获取类的结构
//2.2. 创建对象
//2.2  调用有参构造方法
//2.3. 调用对象的方法 
//2.4. 设置对象的属性值  (重要)
//3. 调用类加载(调用类的静态构造块)  很少使用

JDBC面向接口编程,不面向实现类

    public static void main(String[] args) {
        //1. 重要反射用法, 获取类上的标记的注解
        //获取某个类
        //类对象
        Class<JobService> jobServiceClass = JobService.class;

        //获取JobService类上所有的标注的注解
        Annotation[] annotations = jobServiceClass.getAnnotations();

        for (Annotation annotation : annotations) {
            System.out.println("annotation = " + annotation);

            //注解对象
            Class<? extends Annotation> annotationType = annotation.annotationType();
            System.out.println(annotationType == Service.class);
        }
    }
annotation = @org.springframework.stereotype.Service(value=)
true

2.重要反射用法, 获取属性上的标记的注解

首先需要确保类中存在属性

@Service
public class JobService {
    @Autowired
    private UserService userService;
        //2. 重要反射用法, 获取属性上的标记的注解
        // 获取类 -> 获取类的属性 -> 获取属性上的注解
        Class<JobService> jobServiceClass = JobService.class;
        Field[] declaredFields = jobServiceClass.getDeclaredFields();

        for (Field declaredField : declaredFields) {
            System.out.println("declaredField.getName() = " + declaredField.getName());
        }
declaredField.getName() = userService

重要反射用法, 获取属性上的标记的注解
获取类 -> 获取类的属性 -> 获取属性上的注解

        //2. 重要反射用法, 获取属性上的标记的注解
        // 获取类 -> 获取类的属性 -> 获取属性上的注解
        Class<JobService> jobServiceClass = JobService.class;
        Field[] declaredFields = jobServiceClass.getDeclaredFields();

        for (Field declaredField : declaredFields) {
            System.out.println("declaredField.getName() = " + declaredField.getName());

            //获得当前属性上标记的所有注解
            Annotation[] annotations = declaredField.getAnnotations();
            for (Annotation annotation : annotations) {
                System.out.println(annotation.annotationType() == Autowired.class);
            }
        }
declaredField.getName() = userService
true

此处也可以直接用官方的isAnnotationPresent()方法

        //2. 重要反射用法, 获取属性上的标记的注解
        // 获取类 -> 获取类的属性 -> 获取属性上的注解
        Class<JobService> jobServiceClass = JobService.class;
        Field[] declaredFields = jobServiceClass.getDeclaredFields();

        for (Field declaredField : declaredFields) {
            System.out.println("declaredField.getName() = " + declaredField.getName());
            System.out.println("该方法是否被Autowired注解标记:" + declaredField.isAnnotationPresent(Autowired.class));
        }
  1. 重要反射用法, 获取方法上的标记的注解
    获取类 -> 获取类的方法 -> 获取方法上的注解
//注解的生命周期, 必须是runtime, 表示运行的时候可以被其他人识别
@Retention(RetentionPolicy.RUNTIME)
public @interface BiaoJi {
}
        //3. 重要反射用法, 获取方法上的标记的注解
        // 获取类 -> 获取类的方法 -> 获取方法上的注解
        Class<JobService> jobServiceClass = JobService.class;
        Method[] declaredMethods = jobServiceClass.getDeclaredMethods();

        for (Method declaredMethod : declaredMethods) {
            //获取当前方法上标记的注解
            System.out.println("当前方法名称" + declaredMethod.getName());
            System.out.println("该方法是否被BiaoJi注解标记:" + declaredMethod.isAnnotationPresent(BiaoJi.class));
        }
当前方法名称addJob
该方法是否被BiaoJi注解标记:false
当前方法名称countJob
该方法是否被BiaoJi注解标记:true

//1. 无参构造

扫描JobService.class这个类, 如果有@Service, 则创建对象并置入到hashmap(ioc)

        //spring ioc 如何做的
        //扫描JobService.class这个类, 如果有@Service, 则创建对象并置入到hashmap(ioc)
		//1. 无参构造
        HashMap<String, Object> ioc = new HashMap<>();

        Class aClass = JobService.class;
        if (aClass.isAnnotationPresent(Service.class)){
            //根据当前类对象, 创建一个类的对象
            Object ob = aClass.newInstance();
            //根据name得到小驼峰命名然后放到hashmap中
            String name = aClass.getName();
            ioc.put("jobService", ob);
        }
        System.out.println("ioc = " + ioc);
ioc = {jobService=com.itszt.springbootaop.service.JobService@2f2c9b19}

获取有参构造方法, 然后再调用构造方法

此时构造器只有一个有参构造器

@Service
public class JobService {
   

    public JobService(String data){
        System.out.println("data = " + data);
        System.out.println("JobService.JobService");
    }
        //2. 获取有参构造方法, 然后再调用构造方法
        Constructor<?>[] declaredConstructors = JobService.class.getDeclaredConstructors();
        for (Constructor<?> constructor : declaredConstructors) {
            Object o = constructor.newInstance("张三");
            System.out.println("o = " + o);
        }
data = 张三
JobService.JobService
o = com.itszt.springbootaop.service.JobService@a09ee92

同时存在无参构造器和有参构造器

@Service
public class JobService {

    public JobService(){}

    public JobService(String data){
        System.out.println("data = " + data);
        System.out.println("JobService.JobService");
    }
        //同时存在无参构造器和有参构造器
        Constructor<JobService> declaredConstructor = JobService.class.getDeclaredConstructor(String.class);
        JobService lisi = declaredConstructor.newInstance("lisi");
        System.out.println("lisi = " + lisi);
data = lisi
JobService.JobService
lisi = com.itszt.springbootaop.service.JobService@a09ee92
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值