java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法。这种动态获取类的信息及动态调用类中方法的功能称为java的反射机制。
获取一个类的Class对象是应用反射机制的前提,获取Class对象的方式有如下三种:
-
instance.getClass(),这个是Object类里面的方法
-
Type.Class属性,任何的数据类型,基本数据类型或者抽象数据类型,都可以通过这种方式获取类
- Class.forName("类的全名"),Class类提供了这样一个方法,让我们通过类名来获取到对象类
1. 通过反射机制操作某个类的属性
package net.xsoftlab.baike; import java.lang.reflect.Field; public class TestReflect { private String proprety = null; public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect"); Object obj = clazz.newInstance(); // 可以直接对 private 的属性赋值 Field field = clazz.getDeclaredField("proprety"); field.setAccessible(true); field.set(obj, "Java反射机制"); System.out.println(field.get(obj)); } }
2. 通过反射机制调用某个类的方法
package net.xsoftlab.baike; import java.lang.reflect.Method; public class TestReflect { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect"); // 调用TestReflect类中的reflect1方法 Method method = clazz.getMethod("reflect1"); method.invoke(clazz.newInstance()); // Java 反射机制 - 调用某个类的方法1. // 调用TestReflect的reflect2方法 method = clazz.getMethod("reflect2", int.class, String.class); method.invoke(clazz.newInstance(), 20, "张三"); // Java 反射机制 - 调用某个类的方法2. // age -> 20. name -> 张三 } public void reflect1() { System.out.println("Java 反射机制 - 调用某个类的方法1."); } public void reflect2(int age, String name) { System.out.println("Java 反射机制 - 调用某个类的方法2."); System.out.println("age -> " + age + ". name -> " + name); } }
二、动态代理
2.1 动态代理AOP
java代理模式的定义:用一个对象来控制对另一个对象的访问,称控制对象为代理对象,被控制对象为被代理对象或真实对象。通过调用代理对象的方法来间接访问被代理对象中的同名方法,要保证二者具有同名方法通常将这些同名方法抽象成接口,由二者共同实现。
动态代理和静态代理的区别:静态代理必须要为每个真实类定义一个代理类,而动态代理中无需定义代理类,由java反射包中的Proxy类动态的创建代理对象或代理类。
在java的动态代理机制中,有一个类和接口至关重要,Proxy类用于动态创建代理类或代理对象,调度处理器接口InvocationHandler。每个动态代理对象必须与实现了InvocationHandler接口的实例关联,代理对象每个方法的内部都调用了此关联实例的invoke 方法,而invoke 方法的内部又利用反射机制调用真是对象的方法,从而实现了由代理对象访问真实对象的目的。
下面是实现动态代理的经典案例:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //定义真实类和代理类共同的接口 interface Subject { public void rent(); public void hello(String str); } //定义真实类(被代理类 class RealSubject implements Subject { @Override public void rent() { System.out.println("I want to rent my house"); } @Override public void hello(String str) { System.out.println("hello: " + str); } } //定义继承了InvocationHandler接口的调度处理器 public class MyInvocationHandler implements InvocationHandler { //要代理的真实对象 private Object realObj; // 构造方法给要代理的真实对象赋值 public MyInvocationHandler(Object realObj) { this.realObj = realObj; } /** * 执行动态代理对象的所有方法都会被替换为执行如下的invoke方法 * 其中: * autoProxy:动态代理对象 * method:代表正在执行的方法 * args:由动态代理对象调用方法时传入的实参 */ @Override public Object invoke(Object autoProxy, Method method, Object[] args) throws Throwable { //在代理真实对象前我们可以添加一些自己的操作 System.out.println("before rent invoke"); //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用 System.out.println("Method:" + method); method.invoke(realObj, args); //在代理真实对象后我们也可以添加一些自己的操作 System.out.println("after rent invoke"); return null; } } class Client { public static void main(String[] args) { //要代理的真实对象 Subject realObj = new RealSubject(); //要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的 InvocationHandler MyHandler = new MyInvocationHandler(realObj); /*通过Proxy类的newProxyInstance方法动态创建代理对象 *public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException * 它的三个参数 * 第一个参数 指定动态代理类的类加载器 * 第二个参数 指定动态代理类需实现的接口集合 * 第三个参数 指定与该动态代理对象所关联的调度处理器实例 */ Subject autoProxy = (Subject) Proxy.newProxyInstance(MyHandler.getClass().getClassLoader(), realObj.getClass().getInterfaces(), MyHandler); System.out.println(autoProxy.getClass().getName()); autoProxy.rent(); autoProxy.hello("world"); } }