1.动态代理
(1)动态代理,是实现阶段不关心代理谁,而在运行阶段才指定代理哪一个对象。相对的说,上面两种 普通代理和强制代理,都是通过写代理类来获取代理,这种是静态代理。
(2)区别:静态代理,需要写代理类,在代理之前要知道我代理的是哪个类;
(3)类图
2.代码
接口类
package com.design.代理模式.动态代理; public interface IGamePlayer { void login(String username , String pwd); void killBoss(String name); void upgrade(); }
真实角色
package com.design.代理模式.动态代理; public class GamePlayer implements IGamePlayer { private String name; public GamePlayer() { super(); } public GamePlayer(String _name) { super(); this.name = _name; } // 登录 @Override public void login(String username, String pwd) { System.out.println("GamePlayer:"+ name +" login....."); } // 杀怪 @Override public void killBoss(String name) { System.out.println("GamePlayer:"+ name +" killBoss....."); } // 升级 @Override public void upgrade() { System.out.println("GamePlayer: "+ name +" upgrade....."); } }
继承 InvocationHandler 类的代理类
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; } }
场景类
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通过切点定位到特定的切入点。切入点类似于数据库记录,切点类似于查询条件 */ } }
时间: 2024-10-12 16:13:40