zoukankan      html  css  js  c++  java
  • 设计模式--5.4 代理模式-动态代理

    1.动态代理

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

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

    (3)类图

    2.代码

    接口类

    package com.design.代理模式.动态代理;
    
    public interface IGamePlayer {
        void login(String username , String pwd);
        
        void killBoss(String name);
        
        void upgrade();
    }    
    View Code

    真实角色

    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.....");
    
        }
    
    }
    View Code

    继承 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;
        }
    
    
    
    
    }
    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通过切点定位到特定的切入点。切入点类似于数据库记录,切点类似于查询条件
             */
        }
    }
  • 相关阅读:
    CSLA.Net 3.0.5 项目管理示例 业务基类 Project.cs
    为什么我要写博客
    LINQ 标准的查询操作符 过滤 where、index1、OfType
    LINQ 概述和演变
    sl中几个简单变量的获取
    Rails存储库从SVN转向Git
    showcase测试界面
    Silverlight读取xml
    向silverlight传递自定义参数
    RadRails1.0降临——增加Profiler、CallGraph Analyzer和Rails Shell等新特性
  • 原文地址:https://www.cnblogs.com/fubaizhaizhuren/p/5674380.html
Copyright © 2011-2022 走看看