动态代理Proxy

Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。
代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
要了解 Java 动态代理的机制,首先需要了解以下相关的类或接口:
java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象
// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器
static InvocationHandler getInvocationHandler(Object proxy)

// 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
static Class getProxyClass(ClassLoader loader, Class[] interfaces)

// 方法 3:该方法用于判断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl)

// 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
// 该方法负责集中处理动态代理类上的所有方法调用。
// 第一个参数既是代理类实例,
// 第二个参数是被调用的方法对象
// 第三个方法是调用参数。
// 调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
Object invoke(Object proxy, Method method, Object[] args)
每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象

java.lang.ClassLoader:这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中
每次生成动态代理类对象时都需要指定一个类装载器对象

首先让我们来了解一下如何使用 Java 动态代理。具体有如下四步骤:
1通过实现 InvocationHandler 接口创建自己的调用处理器;
2通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
3通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
4通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入

动态代理对象创建过程
// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
// 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用
InvocationHandler handler = new InvocationHandlerImpl(..);
// 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象
Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... });
// 通过反射从生成的类对象获得构造函数对象
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });
// 通过构造函数对象创建动态代理类实例
Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });

简化的动态代理对象创建过程
// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
InvocationHandler handler = new InvocationHandlerImpl(..);
// 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,
new Class[] { Interface.class }, handler );

package com.ljh.proxy;
public interface Sell {
public void sell();
public void modiy(float price);
}

package com.ljh.test;
import com.ljh.proxy.Sell;
/**
* 真实角色 Dell
* @author Administrator
*
*/
public class Dell implements Sell {
@Override
public void sell() {
System.out.println("Dell sell computer");
}
@Override
public void modiy(float price) {
System.out.println("Dell modify computer neet "+ price);
}
}


package com.ljh.test;
import com.ljh.proxy.Sell;
/**
* 真实角色 Lenover
* @author Administrator
*
*/
public class Lenover implements Sell{
@Override
public void sell(){
System.out.println("Lenover sell computer");
}
@Override
public void modiy(float price) {
System.out.println("Lenover modify computer neet "+price);
}
}


package com.ljh.proxy.impl;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 调用处理器
* @author Administrator
*
*/
public class SellProxy implements InvocationHandler,Serializable{
private static final long serialVersionUID = 1467717578378167352L;
private Object proxy;//为谁生成代理类
public SellProxy(Object obj){
this.proxy = obj;
}
@Override
public Object invoke(Object proxy, //代理类实例
Method method,//被调用的方法对象
Object[] args //方法是调用参数
) throws Throwable {
Object object ;
before();
object = method.invoke(this.proxy, args);
after();
return object;
}
private void after() {
System.out.println("after");
}
private void before() {
System.out.println("before");
}
}

package com.ljh.test;
import java.lang.reflect.Proxy;
import com.ljh.proxy.Sell;
import com.ljh.proxy.impl.SellProxy;
public class ProxyTest {
public static void main(String[] args) {
//创建真实角色类
Sell sell = new Lenover();
//创建调用管理器类
SellProxy handler = new SellProxy(sell);//传入需要需要代理的真实角色
Sell proxy = (Sell) Proxy.newProxyInstance(
sell.getClass().getClassLoader(), //指定加载器来加载动态生成的代理类字节码
new Class[]{Sell.class},// 根据指定一组接口来生成代理类的实例
handler);// 调用处理器类
proxy.sell();
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值