15_Java反射机制——5.反射的应用:动态代理
目录
问题一: 动态代理的概念
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时,
根据实际需要,动态地创建目标类的代理对象。
问题二: 动态代理和静态代理相比,动态代理的优势
抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,
这样,就可以更加灵活和统一的处理众多的方法。
问题三: 动态代理的使用场景
调试和远程方法调用
1. Java 动态代理相关API
1) Proxy : 专门完成代理的操作类,是所有动态代理类的父类。
通过此类可以为一个或多个接口动态地生成实现类。
2) Proxy : 提供了用于创建动态代理类和动态代理对象的静态方法
// 创建一个动态代理类所对应的Class对象
static Class<?> getProxyClass(ClassLoader loader, Class<?>... Interfaces)
// 创建一个动态代理对象, loader: 类加载器;interfaces: 被代理类(原始类)实现的全部接口; h: 得到 InvocationHandler 接口的实现类实例。
static Object newProxyInstance(ClassLoader loder, Class<?>[] interfaces, InvocationHandler h)
2. 动态代理的实现
实现动态代理要解决的问题
1) 问题:如何通过 加载到 内存中的类(被代理类 —— 原始类),动态创建代理类及其对象
// 创建一个动态代理类所对应的Class对象
static Class<?> getProxyClass(ClassLoader loader, Class<?>... Interfaces)
// 创建一个动态代理对象, loader: 类加载器;interfaces: 被代理类(原始类)实现的全部接口; h: 得到 InvocationHandler 接口的实现类实例。
static Object newProxyInstance(ClassLoader loder, Class<?>[] interfaces, InvocationHandler h)
2) 问题:如何通过 代理类对象的同名方法的调用,去实现 被代理类(原始类)的同名方法的调用
在 InvocationHandler 接口中,有 invoke 方法, 可以通过实现该接口,来重写 invoke 方法 从而实现 被代理类对象的同名方法的调用。
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 调用 被代理类对象的同名方法,得到其方法调用的返回值
Object realReturnValue = method.invoke(target, args);
return realReturnValue;
}
实现动态代理举例
【1. 创建一个 Plant 接口】
public interface Plant {
public void photosynthesis();
public void breath();
}
【2. 创建一个 被代理类(原始类) BigTree】
package com.atzwx.java;
// 被代理类 (原始类)
public class BigTree implements Plant {
@Override
public void photosynthesis() {
System.out.println("被代理的类 —— BigTree.photosynthesis");
}
@Override
public void breath() {
System.out.println("被代理的类 —— BigTree.breath");
}
}
【3. 创建一个 实现 InvocationHandler 接口的 MyInvocationHandler类,重写 invoke方法,实现动态代理的具体操作】
package com.atzwx.java;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
// 设置 指定的 被代理类(原始类)
public void setTarget(Object target) {
this.target = target;
}
/**
* 通过代理类对象 调用同名方法, 来实现 被代理类(原始类)对象 调用同名方法
* @param proxy 调用方法的代理对象
* @param method 代理类对象调用的同名方法
* @param args 同名方法的形式参数
* @return 被代理类对象的同名方法的真实返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
PlantUtil plantUtil = new PlantUtil();
// 调用 通用方法1
// plantUtil.universalMethod1();
// 调用 被代理类对象的同名方法,得到其方法调用的返回值
Object realReturnValue = method.invoke(target, args);
// 调用 通用方法2
// plantUtil.universalMethod2();
return realReturnValue;
}
}
【4. 创建一个 代理类 ProxyObjectFactory】
package com.atzwx.java;
import java.lang.reflect.Proxy;
// 代理类
public class ProxyObjectFactory {
/**
* 创建一个动态代理类对象
* @param target 为被代理类(原始类) 的 对象
* @return
*/
public static Object getProxyInstance(Object target) {
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
// 用于实现 处理代理类 与 被代理类 的同名方法调用
MyInvocationHandler invocationHandler = new MyInvocationHandler();
invocationHandler.setTarget(target);
// 返回一个代理类对象
return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
}
【5. 调用 代理类对象的同名方法】
package com.atzwx.test;
import com.atzwx.java.BigTree;
import com.atzwx.java.Employee;
import com.atzwx.java.Plant;
import com.atzwx.java.ProxyObjectFactory;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTest {
/**
* 反射的应用:动态代理
*
*/
@Test
public void dynamicProxy() {
// 1. 创建一个 被代理类 对象
BigTree bigTree = new BigTree();
// 2. 创建一个 代理类对象
Plant plant = (Plant) ProxyObjectFactory.getProxyInstance(bigTree);
// 3. 代理类对象的同名方法的调用,去实现 被代理类对象的同名方法的调用
plant.photosynthesis();
System.out.println();
plant.breath();
}
}
【output】
被代理的类 —— BigTree.photosynthesis
被代理的类 —— BigTree.breath
3. 动态代理 与 AOP (Aspect Orient Programming) 简单举例
【新建一个 PlantUtil 类,在该类中编写通用方法】
package com.atzwx.java;
public class PlantUtil {
public void universalMethod1() {
System.out.println("==============PlantUtil.universalMethod1==============");
}
public void universalMethod2() {
System.out.println("==============PlantUtil.universalMethod2==============");
}
}
【在 MyInvocationHandler 类中的 invoke 方法里,添加通用方法】
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
PlantUtil plantUtil = new PlantUtil();
// 调用 通用方法1
plantUtil.universalMethod1();
// 调用 被代理类对象的同名方法,得到其方法调用的返回值
Object realReturnValue = method.invoke(target, args);
// 调用 通用方法2
plantUtil.universalMethod2();
return realReturnValue;
}
【调用 动态代理类 Plant 对象的同名方法】
plant.photosynthesis();
System.out.println();
plant.breath();
【output】
==============PlantUtil.universalMethod1==============
被代理的类 —— BigTree.photosynthesis
==============PlantUtil.universalMethod2==============
==============PlantUtil.universalMethod1==============
被代理的类 —— BigTree.breath
==============PlantUtil.universalMethod2==============