Dynamic Proxy

首先抛出问题:

1.什么是动态代理?  2.动态代理有什么用? 3.如何实现动态代理? 4.深入动态代理源码级

今天讲的是JDK实现的动态代理。据说是spring的AOP模块的核心。

那么什么是动态代理呢? 我们知道在程序中会写很多种方法,

那么现在问题来了:

我想实现在运行时期动态的改变某些写死的方法,继而增加一些我想要的方法,该怎么做呢?

动态代理实现的就是这个功能。

由此我么可以猜想,动态代理一定用到了java的反射机制。没错!来看代码

首先我们有一个接口 PInterface:

接口中给出两个公共的方法:

  public void eat();

  publci void end();

然后给出一个实现了此接口的实现类UserClass,我们称之为:用户类。

  实现这两个方法:

 public void eat(){System.out.println("吃啥");}

 public void end(){System.out.println("刷碗);}

然后我们的重头戏来了:代理类ProxyClass,首先我们的这个代理类需要继承InvocationHandler接口,给出这个接口中的方法:如下

package java.lang.reflect;

public interface InvocationHandler {

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
可以看到在这个接口中唯一的方法就是invoke方法,这个方法的用法是什么呢?一起来看。

在invoke方法中有三个参数,分别是Object类型的proxy,Method类型的method参数,数组类型的args。

首先proxy对象代表的是我们要代理的类,而method就是我们传入的方法,代理对象就是根据我们传入的方法来确定所要代理的对象,以及数组args。

我们这里给出自己定义的代理类方法:

private Object targetObject;

public Object newProxyInstance(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object ret = null;

try {
System.out.println("正在进行操作前的准备工作……");
//调用目标方法
ret = method.invoke(targetObject, args);
System.out.println("操作成功,正在进行确认处理……");
} catch (Exception e) {
e.printStackTrace();
System.out.println("error-->>" + method.getName());
throw e;
}
return ret;

首先要做的是:私有化一个Object的对象。

然后提供一个实例化代理实例的方法,在这个方法中,将Object类型的目标对象赋给使用这个方法的对象,返回当前代理对象的实例。

在invoke方法中,定义代理方法以及之前的用户类的代理方法。

我们来看一下这个方法的定义:

public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}

再来看一下JDK对于两个参数的解释和使用说明:

@param obj the object the underlying method is invoked from
@param args the arguments used for the method call

由此可见第一个参数是实例对象,而第二个参数是唤起方法,也就是使用哪个方法来唤起代理对象。

在Client测试类中这样写:

ProxyClass dp = new ProxyClass();
PInterface userManager = (UserClass)dp.newProxyInstance(new ImpleClass());
UserClass.eat(); 

首先实例化我们的代理类对象。

然后调用实例化代理对象方法,赋给用户类。至于为什么代理类对象可以类型强转成用户类对象,大家可以思考一下。

最后用户类调用eat方法唤起代理对象。

最后执行结果是:

晚饭时间到
吃啥
吃炸鸡和啤酒吧

可以看到代理 类对于用户来说是透明的,用户只需要实例化一个代理类对象即可,至于代理类中的方法定义与用户无关。

用户看不到代理类是如何工作的,但是可以满足动态增加想要实现的功能的需求。

后续会继续分析Proxy.newProxyInstance()这个方法。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值