浅谈Spring6中的反射机制

 更新时间:2023年05月17日 08:37:58   作者:@每天都要敲代码  
Java反射机制是Java语言中一种动态(运行时)访问、检测、修改它本身的能力,主要作用是动态(运行时)获取类的完整结构信息、调用对象的方法,需要的朋友可以参考下

一:回顾反射机制

这种重点回顾一下反射Method!

为什么要回顾反射机制呢?因为我们后面要手写一个简易的Spring框架,便于我们理解其中的核心原理!

1. 分析方法四要素

我们先来看一下,不使用反射机制调用一个方法需要几个要素的参与!

定义一个SomeService方法

package com.bjpowernode.reflect;
public class SomeService {
    // 没有参数、没有返回值的方法
    public void doSome(){
        System.out.println("public void doSome()执行。");
    }
    // 一个参数,返回String的方法
    public String doSome(String s){
        System.out.println("public String doSome(String s)执行。");
        return s;
    }
    // 两个参数,返回String的方法
    public String doSome(String s, int i){
        System.out.println("public String doSome(String s, int i)执行。");
        return s + i;
    }
}

进行测试,分析方法的要素

package com.bjpowernode.reflect;
public class Test {
    public static void main(String[] args) {
        // 不使用反射机制调用这些方法
        SomeService someService = new SomeService();
        // 无参数
        someService.doSome();
        // 一个参数
        String s1 = someService.doSome("张三");
        System.out.println(s1);
        // 两个参数
        String s2 = someService.doSome("李四", 250);
        System.out.println(s2);
    }
}

通过以上测试代码,我们可以得出调用一个方法,一般涉及到4个要素:

①调用哪个对象的(SomeService)

②哪个方法(doSome)

③传什么参数("张三")

④返回什么值(String类型)

总结:调用哪个对象哪个方法传什么值返回什么值

2. 获取Method

要使用反射机制调用一个方法,首先你要获取到这个方法。

在反射机制中Method实例代表的是一个方法,那么怎么获取Method实例呢?

编写测试

(1)要想调用方法,首先我们要先获取对应的类,使用Class.forName,参数是全限定类名

(2)然后调用这个类的getDeclaredMethod方法,参数一个是方法名、另一个参数是可变可变长度参数,类型是class;这样就能获取到方法。

(3)方法获取到,我们就可以调用invoke(调用)方法,参数一个是obj,就是要把对象传过来,所以我们就需要先创建一个对象、另一个参数也是可变长度参数,传具体的值。

例如以下程序的四要素:调用哪个对象、哪个方法、传什么参数、返回什么值?

①obj 要素:哪个对象

②doSomeMethod 要素:哪个方法

③"李四", 250 要素:传什么参数

④retValue 要素:返回什么值

package com.bjpowernode.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Test2 {
    public static void main(String[] args) throws Exception{
        // 使用反射机制调用方法
        // 第一步:获取类
        Class<?> clazz = Class.forName("com.bjpowernode.reflect.SomeService");
        // 第二步:获取方法
        Method doSomeMethod = clazz.getDeclaredMethod("doSome", String.class, int.class);
        // 第三步:调用方法,四要素
        // 创建对象
        Object obj = clazz.newInstance(); // 这个方法已经过时,也可以采用其它方式
        // 也可以先获取到无参数构造方法,然后在创建对象
        Constructor<?> declaredConstructor = clazz.getDeclaredConstructor();
        Object obj1 = declaredConstructor.newInstance();
        // 调用invoke方法
        Object retValue = doSomeMethod.invoke(obj, "李四", 250);
        System.out.println(retValue);
    }
}

3. SpringDI核心实现原理

我们在看一下下面这种需求,假设你现在已知以下信息: ①有这样一个类,类名叫做:com.powernode.reflect.User ②这个类符合javabean规范。属性私有化,对外提供公开的setter和getter方法。 ③你还知道这个类当中有一个属性,属性的名字叫做 age ④并且你还知道age属性的类型是int类型。要求:请使用反射机制调用set方法,给User对象的age属性赋值!

User类

package com.bjpowernode.reflect;
public class User {
    private String name;
    private int age;
    public User() {
    }
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

使用反射机制进行赋值,通用代码

第一步:还是通过反射机制先获取类,Class.forName

第二步:调用getDeclaredMethod方法获取方法,参数有两个,怎么样动态获取呢?

①已知了属性名是age,又符合javabean规范,所以我们可以动态拼接出方法名:先拼接上“set”,再调用toUpperCase方法全部转换成大写,然后调用charAt方法截取第一个字符;最后在调用substring方法拼接上后面的字符串;得到完整的方法名:getAge

②已知了属性名是age,调用类的getDeclaredField方法,参数是属性名age,就可以获取对应的属性类型,但是我们需要的是.class,所以在调用参数类型的getType方法;得到完整的属性类型(.class形式):int.class

第三步:最后就可以创建对象,调用invoke方法,给属性赋值,这个方法没有返回值类型,所以什么都不要返回;最后输出这个对象即可!

package com.bjpowernode.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Locale;
public class Test4 {
    public static void main(String[] args) throws Exception {
        // 已知类名和属性名
        String className = "com.bjpowernode.reflect.User";
        String propertyName = "age";
        // 使用反射机制,给age属性赋值
        // 第一步:获取类
        Class<?> clazz = Class.forName(className);
        // 第二步:获取方法
        // 根据属性获取方法名---字符串拼接
        String setMethodName = "set"+propertyName.toUpperCase().charAt(0)+propertyName.substring(1);
        // 根据属性获取属性的类型
        Field filedType = clazz.getDeclaredField(propertyName);
        // 获取方法
        Method setMethod = clazz.getDeclaredMethod(setMethodName, filedType.getType());
        // 第三步:调用
        // 创建对象
        Object obj = clazz.newInstance();
        setMethod.invoke(obj,18); // 没有返回值类型
        // 输出打印这个对象
        System.out.println(obj);
    }
}

执行结果:age属性成功赋值 

看到这里我们是不是想到了Spring容器的注入?我们在看一下我们配置的spring.xml文件,就是指定了类名和属性名;然后底层通过反射机制进行了对象的创建!

 总结:有了上面我们对反射机制的回顾学习,后面我们就尝试手写一个简易的Spring框架!

到此这篇关于浅谈Spring6中的反射机制的文章就介绍到这了,更多相关Spring6反射机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot结合JWT实现用户登录、注册、鉴权

    SpringBoot结合JWT实现用户登录、注册、鉴权

    用户登录、注册及鉴权是我们基本所有系统必备的,也是很核心重要的一块,本文主要介绍了SpringBoot结合JWT实现用户登录、注册、鉴权,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2023-05-05
  • Mybatis 动态SQL搭建环境的全过程

    Mybatis 动态SQL搭建环境的全过程

    这篇文章主要给大家介绍了关于Mybatis动态SQL搭建环境的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • SpringBoot监听器的实现示例

    SpringBoot监听器的实现示例

    在SpringBoot中,你可以使用监听器来响应特定的事件,本文主要介绍了SpringBoot监听器的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • Spring Bean实例的创建及构造器的挑选

    Spring Bean实例的创建及构造器的挑选

    这篇文章主要介绍了Spring Bean实例的创建及构造器的挑选,文中有非常详细的代码示例,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下
    2021-04-04
  • JAVA基于Redis实现计数器限流的使用示例

    JAVA基于Redis实现计数器限流的使用示例

    计数器法是限流算法里最简单也是最容易实现的一种算法,本文主要介绍了JAVA基于Redis实现计数器限流的使用示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • IDEA调试功能使用总结(step over/step into/force step into/step out)

    IDEA调试功能使用总结(step over/step into/force step into/step o

    本文主要介绍了IDEA调试功能使用总结(step over/step into/force step into/step out),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 如何解决 Java 中的 IndexOutOfBoundsException 异常(最新推荐)

    如何解决 Java 中的 IndexOutOfBoundsException 异

    当我们在 Java 中使用 List 的时候,有时候会出现向 List 中不存在的位置设置新元素的情况,从而导致 IndexOutOfBoundsException 异常,本文将会介绍这个问题的产生原因以及解决方案
    2023-10-10
  • Java实现UTF-8编码与解码方式

    Java实现UTF-8编码与解码方式

    这篇文章主要介绍了Java实现UTF-8编码与解码方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • jmeter接口测试教程及接口测试流程详解(全网仅有)

    jmeter接口测试教程及接口测试流程详解(全网仅有)

    Jmeter是由Apache公司开发的一个纯Java的开源项目,即可以用于做接口测试也可以用于做性能测试。本文给大家分享jmeter接口测试教程及接口测试流程,感兴趣的朋友跟随小编一起看看吧
    2021-12-12
  • IDEA 开发多项目依赖的方法(图文)

    IDEA 开发多项目依赖的方法(图文)

    这篇文章主要介绍了IDEA 开发多项目依赖的方法(图文),本文讲一下关于使用IntelliJ IDEA基于Maven创建多模块项目的实际开发,非常具有实用价值,需要的朋友可以参考下
    2018-10-10

最新评论