java反射
反射概念
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。 这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。
- 实现对象的创建
- 实现了解对象的类的所有属性。
反射的实现方法?
- Class.forName(“类的路径”)
- 类名.class
- 对象名.getClass()
- 基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象
利用反射动态创建对象实例
Class 对象的 newInstance()
使用 Class 对象的 newInstance()方法来创建该 Class 对象对应类的实例,但是这种方法要求该 Class 对象对应的类有默认的空构造器。
调用 Constructor 对象的 newInstance()
先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的 newInstance()方法来创建 Class 对象对应类的实例,通过这种方法可以选定构造方法创建实例。
1 2 3 4 5 6 7 8
//获取 Person 类的 Class 对象 Class clazz=Class.forName("reflection.Person"); //使用.newInstane 方法创建对象 Person p=(Person) clazz.newInstance(); //获取构造方法并创建对象 Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class); //创建对象并设置属性13/04/2018 Person p1=(Person) c.newInstance("李四","男",20);
spring与反射
创建 Bean 实例时的反射
|
|
构造方法依赖注入时的反射
|
|
class 文件与类对象
class 文件由 java 文件编译而来,class 文件包含字段表、方法表、<init>
方法(构造方法)等。
当类加载器将 class 文件加载进虚拟机元数据区(方法区,jdk1.7)时,虚拟机创建一个与之对应的类对象(Class 实例)。并将 class 文件由存放在磁盘的静态结构转换为存放在内存的运行时结构。
我们可以认为一个类(class 文件)对应一个类对象,当前类的所有对象共用一个类对象。类对象作为访问存放在 jvm 的 class 文件的入口。
反射与注解
注解:@Override
这样的就是注解,注解本身并不会给类或者方法加入什么新的功能。注解仅仅只是一个标识,真正逻辑work的是反射。
真正给注解实现新的功能的,是反射。通过反射,可以动态获取到目标对象的类的,方法的变量的属性。进而可以判断这个类,方法,变量有没有用到某个注解。进而实现代理调用,执行。
不懂注解?那就自己写一个,安排的明明白白_哔哩哔哩_bilibili
注解实现
|
|
spring的反射与注解
IOC
Spring框架中的反射通常在应用程序启动时工作**。当Spring容器启动时,它会扫描应用程序中的类和配置,然后根据配置信息实例化和管理相应的对象。**在这个过程中,Spring可能会使用Java的反射机制来动态地创建对象、调用方法以及设置属性。这种动态性使得Spring框架能够在不直接依赖于类的具体实现的情况下,根据配置信息创建和管理对象,从而实现了松耦合和灵活性。
假设我们有一个名为UserService
的服务类,我们希望Spring能够管理它,并在需要时注入到其他类中。首先,我们需要将该类标记为Spring管理的组件,通常使用@Component
注解来实现:
注意:
因此,无论是 @Component
还是 @Service
注解,它们在实际的反射执行过程中没有任何区别,都可以被Spring框架扫描到并注册为Bean。区别仅在于语义上的意图和约定,以及在编码规范和可读性上的区别。!!!
|
|
在应用程序启动时,Spring框架会扫描类路径以及包名**,寻找标记有@Component
注解的类,并将它们实例化为bean并加入到Spring容器中**。在这个过程中,Spring可能会使用反射机制来创建类的实例。
另外,假设我们有一个名为UserController
的控制器类,它需要依赖于UserService
。我们可以使用构造函数注入的方式告诉Spring容器,当创建UserController
实例时,需要注入UserService
实例:
|
|
AOP
假设我们有一个需求,希望在执行某个方法之前和之后记录日志。我们可以通过定义一个切面来实现这个需求:
|
|
下面是Spring AOP使用反射的基本原理:
- 创建代理对象:当Spring容器启动时,它会扫描定义的切面,并为匹配切点的bean创建代理对象。Spring AOP通常使用Java动态代理实现代理对象。通过
java.lang.reflect.Proxy
类的newProxyInstance()
方法创建代理对象。这个代理对象实现了目标类所实现的所有接口,并且可以拦截接口方法的调用。 - 拦截方法调用:代理对象拦截匹配切点的方法调用。当某个被代理的方法被调用时,代理对象会触发
InvocationHandler
接口中的invoke()
方法。 - 调用通知方法:在
invoke()
方法中,Spring使用反射API来定位并调用与切面匹配的通知方法。这涉及到解析切面中定义的切点表达式,并定位匹配的通知方法。 - 执行目标方法:在通知方法调用之前或之后,代理对象会调用目标方法。它使用反射API定位目标方法,并调用它。