您的位置:首页 > 其它

设计模式--5.4 代理模式-动态代理

2016-07-15 17:42 309 查看
1.动态代理

(1)动态代理,是实现阶段不关心代理谁,而在运行阶段才指定代理哪一个对象。相对的说,上面两种 普通代理和强制代理,都是通过写代理类来获取代理,这种是静态代理。

(2)区别:静态代理,需要写代理类,在代理之前要知道我代理的是哪个类;

(3)类图

package com.design.代理模式.动态代理;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class GamePlayIH implements InvocationHandler {

// 被代理者
Class<?> cls = null;

// 被代理者的实例
Object obj = null;

// 我要代理谁 _obj
public GamePlayIH(Object _obj) {
super();
this.obj = _obj;
}

// 调用被代理者的方法
// invoke方法,完成对真实方法的调用
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

// 参数
if(args != null){
for(int i = 0 ; i < args.length ; i++){
System.out.println("参数" + args[i]);
}
}

// 前置通后
System.out.println("前置通知。。。");

// 执行方法,及结果
Object result = method.invoke(this.obj, args);

// 后置通知
if(method.getName().equalsIgnoreCase("login")){
System.out.println("有人盗我的号!!");
}

// 后置通知
System.out.println("后置通知。。。");

return result;
}

}


View Code
场景类

package com.design.代理模式.动态代理;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client {
public static void main(String[] args) {
// 定义一个游对玩家
IGamePlayer gp = new GamePlayer("lvyf");

// 定义一个handler
InvocationHandler handler = new GamePlayIH(gp);

// 获得类的classLoader,代理对象由哪一个类加载器加载
ClassLoader cl = gp.getClass().getClassLoader();

// 代理对象的类型,即其中有哪些方法
Class<?>[] interfaces = gp.getClass().getInterfaces();

// 动态产生一个代理者
IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl, interfaces, handler);

// 登录
proxy.login("lvyf", "123");
proxy.killBoss("lvyf");
proxy.upgrade();

/*
* 说明
* 1. IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl, interfaces, handler);
* 需要使用代理,所以这句话是重新生成一个对象
* 2. gp.getClass().getInterfaces(); 这句话是查找类的所有接口,然后由handler实现所有接口
* 3. 由handler里面的invoke方法去接管方法的实现
* 4. 调用过程
*     Client ------>   Proxy  ---invoke--->  GamePlayIH  ---invoke--->   IGamePlayer
* 5. 动态代理就是横向切面编程,在不改变已有代码结构的情况下,增强或控制对象的行为
* 6. 注意,被代理类GamePlayer必须要实现一个接口IGamePlayer(CGLIB不用)
*
* 7.(1) 切面,横切关注点被模块化之后的特殊对象。
* (如,我在调某个加方之前,希望打印日志,把参数打印出来,)你这个需求就叫横切关注点,打印日志被抽离出来模块化,这个模块化对象就叫做日志切面。
*      (2) 切入点 jointpoint,比如我希望在加法之前打印日志,那么在加法之前,就叫切入点,joinpoint,或者执行后,打印结果,这个执行后,也叫切入点
*   (3) 通知,切面必须要完成的工作,如日志,权限验证,叫做通知
*   (4) 织入,比如打印日志这个动作,就叫织入
*   (5) 切点 pointcut,aop通过切点定位到特定的切入点。切入点类似于数据库记录,切点类似于查询条件
*/
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: