当前位置: 首页 > news >正文

什么是反射,反射用途,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

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.26</version>
</dependency>

例子:首先创建一个基类

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;}@Overridepublic 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);@Testvoid test1() {//构造Constructor<Student> constructor = ReflectUtil.getConstructor(Student.class);// 获取字段Field field = ReflectUtil.getField(Student.class, "name");
//        Map<String, Field> fieldMap = ReflectUtil.getFieldMap(Student.class);//获取所有字段Field[] fields = ReflectUtil.getFields(Student.class);//设置字段值ReflectUtil.setFieldValue(student, "name", "李四");//获取指定字段值Object fieldValue = ReflectUtil.getFieldValue(student, "name");}@Testvoid 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赋值。


http://www.mrgr.cn/news/34581.html

相关文章:

  • Mysql进阶
  • 一篇关于网络的文章
  • 研一奖学金计划2024/9/23有感
  • BEV学习--Nuscenes数据集解读
  • 用Flowise+OneAPI+Ollama做一个在线翻译工作流
  • 如何登录通义灵码,快速开启AI编码之旅?
  • 基于单片机巡迹避障智能小车系统
  • 设计模式相关知识
  • SpringBoot+Aop+注解方式 实现多数据源动态切换
  • vcruntime140_1.dll无法继续执行代码的6种解决方法
  • Undet for sketchup 2023.3注册机 支持草图大师sketchup2021-2022-2023
  • 数据结构之图的遍历
  • MySQL | 使用 HAVING 子句进行高级数据筛选
  • 数据链路层协议 —— 以太网协议
  • 如何快速免费搭建自己的Docker私有镜像源来解决Docker无法拉取镜像的问题(搭建私有镜像源解决群晖Docker获取注册表失败的问题)
  • 全栈开发(四):使用springBoot3+mybatis-plus+mysql开发restful的增删改查接口
  • 代码随想录算法训练营Day11
  • JDK7u21 HashMap版
  • C++之STL—vector容器进阶篇
  • Spring源码学习:SpringMVC(2)DispatcherServlet初始化【子容器9大组件】