什么是反射,反射用途,spring哪些地方用到了反射,我们项目中哪些地方用到了反射

分类: 365不让提款 发布时间: 2025-09-25 10:08:18
作者: admin 阅读: 6444 | 点赞: 316
什么是反射,反射用途,spring哪些地方用到了反射,我们项目中哪些地方用到了反射

3分钟搞懂Java反射

一、反射是什么

在Java中,反射(Reflection)是一种强大的工具,它允许程序在运行时获取和操作类、接口、构造器、方法和字段等。反射是Java语言的一个重要特性,它为开发人员提供了许多灵活性,尤其是在构建框架和库时非常有用。

二、获取Class对象的三种方式

1.Class c1 =类名.class

public class MyClass {

public static void main(String[] args) {

Class myClass = MyClass.class; // 获取 MyClass 的 Class 对象

System.out.println(myClass.getName()); // 输出: com.beiyou.example.MyClass

}

}

2.通过 instance.getClass() 方法,如果你有一个类的实例,你可以调用 getClass() 方法来获取其 Class 对象

public class MyClass {

public static void main(String[] args) {

MyClass instance = new MyClass();

Class myClass = instance.getClass(); // 获取 MyClass 实例的 Class 对象

System.out.println(myClass.getName()); // 输出: com.beiyou.example.MyClass

}

}

3.通过 Class.forName() 方法,通过全类名动态加载类,并获取其 Class 对象

public class MyClass {

public static void main(String[] args) throws ClassNotFoundException {

Class myClass = Class.forName("com.example.MyClass"); // 动态加载 MyClass 的 Class 对象

System.out.println(myClass.getName()); // 输出: com.example.MyClass

}

}

Java

三、反射的主要用途包括

1.获取类信息:获取类名、包名、父类、接口等。

获取类名:myClass.getName()

获取类的属性:c1.getField(),只能获取public修饰的属性,getDeclaredField(),获取任意修饰符修饰的属性

获取方法:c1.getMethod(),只能获取public的方法,getDeclaredMethodes()获取任意修饰符修饰的方法,

2.创建实例:通过类名或Class对象动态创建实例。

3.访问类成员:获取并操作类的字段、方法和构造器。

也可以使用 Hutool 中的ReflectUtil 类中的方法来操作类的方法和属性。使用Hutool前记得引用Hutool

cn.hutool

hutool-all

5.8.26

例子:首先创建一个基类

import lombok.Data;

@Data

public class Student {

public int id;

public String name;

private int age;

public Student() {

}

public Student(int id, String name, int age) {

this.id = id;

this.name = name;

this.age = age;

System.out.println("这是构造");

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

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 "Student{" +

"id=" + id +

", name='" + name + '\'' +

", age=" + age +

'}';

}

public void say() {

System.out.println("hello++++++");

}

public void eat() {

System.out.println("吃饭------");

}

}

测试类test1

import cn.hutool.core.util.ReflectUtil;

import com.beiyou.model.Student;

import org.junit.jupiter.api.Test;

import org.springframework.boot.test.context.SpringBootTest;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.util.Map;

@SpringBootTest

class RefleUtilAppTests {

//创建实例

Student student = ReflectUtil.newInstance(Student.class, 1, "张三", 18);

@Test

void test1() {

//构造

Constructor constructor = ReflectUtil.getConstructor(Student.class);

// 获取字段

Field field = ReflectUtil.getField(Student.class, "name");

// Map fieldMap = ReflectUtil.getFieldMap(Student.class);

//获取所有字段

Field[] fields = ReflectUtil.getFields(Student.class);

//设置字段值

ReflectUtil.setFieldValue(student, "name", "李四");

//获取指定字段值

Object fieldValue = ReflectUtil.getFieldValue(student, "name");

}

@Test

void test2() {

Student student = ReflectUtil.newInstance(Student.class, 1, "张三", 18);

// 获取所有方法

Method[] methods = ReflectUtil.getMethods(Student.class);

for (Method m : methods) {

System.out.println(m.getName());

}

// 获取指定方法

Method method = ReflectUtil.getMethod(Student.class, "say");

System.out.println(method.getName());

// 执行方法

ReflectUtil.invoke(student, "say");

}

}

测试类2

import cn.hutool.core.util.ReflectUtil;

import com.beiyou.model.Student;

import org.junit.jupiter.api.Test;

import org.springframework.boot.test.context.SpringBootTest;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

class ReflectionAppTests {

public static void main(String[] args) {

Class studentClass = null;

try {

//获取类对象

studentClass = Class.forName("com.beiyou.model.Student");

// 获取构造器

Constructor constructor = studentClass.getConstructor();

//创建实例

Object instance = studentClass.newInstance();

//获取属性

Field name = studentClass.getField("name");

name.set(instance, "张三");

System.out.println("name : " + name.get(instance));

Field age = studentClass.getDeclaredField("age");

age.setAccessible(true);

age.set(instance, 20);

System.out.println(" age : " + age.get(instance));

} catch (Exception e) {

e.printStackTrace();

}

}

}

效率:通过new获取对象的操作要比通过反射获取对象速度快得多。根据情况选择使用new还是反射。

四、Spring框架中哪里用到了反射

1. 依赖注入:Spring通常使用反射机制来创建和初始化 Bean。

依赖注入三种方式:构造方法注入,set方法注入和属性注入

2. AOP:代理方式分为动态代理和静态代理,静态代理是我们手写的,动态代理分为Spring动态Spring AOP 使用 JDK 动态代理或者 CGLIB 字节码增强技术来实现 AOP 的切面逻辑,这其中就包含了对被代理对象方法的反射调用。JDK 动态代理适用于实现了接口的目标对象。Spring 使用 java.lang.reflect.Proxy 类来创建代理对象,并且使用 InvocationHandler 接口来定义方法拦截逻辑。

3. MVC 框架:Spring MVC 框架使用反射来调用相应的控制器方法,从而实现请求的处理。

4. 数据库访问框架:Spring 的 JDBC 框架使用反射机制来实现对数据库的访问。

5. 容器管理:Spring 容器也使用了反射机制来管理对象的实例化和依赖注入。

五、我们在项目哪里用到了反射

MyBatis拦截器处理参数时使用,在做WMS仓储系统时,我们的数据表中都有lastUpdatBy这个字段,我们绝大多数业务都需要对lastUpdateBy进行赋值,所以我们就在Mybatis拦截器中通过反射获取参数,然后通过ThreadLocal中的localuser进行统一对其赋值。ThreadLocal为每一个线程提供一个独立的变量副本,使得每个线程在访问变量时获取的都是自己独有的线程副本,ThreadLocal能够实现跨类跨方法实现变量的传递。我们定义了一个LocalUser对象存储在ThreadLocal中,然后就可以获取ThreadLocal中的Localuser对象为lastUpdateBy赋值。