• 代理模式-jdk动态代理


    IDB 

    package com.bjpowernode.proxy;
    
    /**
     * 代理类和目标类都必须使用同一个接口。 
     */
    public interface IDB {
        
        int insert();
        int delete();
        int update();
    }

    OracleDB 

    package com.bjpowernode.proxy;
    
    /**
     * 这是一个Oracle数据库相关的操作类
     * 
     * 目标类(委托类)。
     */
    public class OracleDB implements IDB{
        public int insert(){
            
            //以下是一个插入操作
            System.out.println("Oracle insert data....");
            try {
                Thread.sleep(526);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 0;
        }
        
        
        public int delete(){
            
            //以下是一个删除操作
            System.out.println("Oracle delete data....");
            try {
                Thread.sleep(569);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            return 0;
        }
        
        
        public int update(){
            
            //以下是一个更新操作
            System.out.println("Oracle update data....");
            try {
                Thread.sleep(456);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            return 0;
        }
        
    }

    TimeInvocationHandler 

    package com.bjpowernode.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * 注册在这个接口中的代码,在代理对象调用代理方法的时候,自动执行。
     * 我们的扩展代码就注册在这个类中。
     */
    public class TimeInvocationHandler implements InvocationHandler {
    
        //这个程序运行期,obj引用中保存了内存地址指向的对象是一个目标对象。
        private Object obj;
        
        public TimeInvocationHandler(Object obj){
            this.obj = obj;
        }
        
        /**
         * proxy 是代理对象的引用。
         * method 是目标类中的目标方法
         * args 是目标类中的目标方法的实参
         */
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            
            long begin = System.currentTimeMillis();
            
            //通过反射机制去调用目标类中的目标方法
            Object retValue = method.invoke(obj, args);
            
            long end = System.currentTimeMillis();
            System.out.println("方法执行所耗费" + (end-begin) + "毫秒");
            
            return retValue;
        }
    
    }

    Test 

    package com.bjpowernode.proxy;
    
    import java.lang.reflect.Proxy;
    
    public class Test {
    
        public static void main(String[] args) {
            
            //创建目标类对象
            IDB db = new OracleDB();
            
            //创建代理对象
            //DBProxy dbProxy = new DBProxy(); //这是静态代理模式中创建对象,因为DBProxy是我们程序员手动编写的。
            
            //创建代理对象(这次创建代理对象是交给JVM完成,包括在这个过程中,JVM也会自动生成“代理类的字节码”)
            //这个代理类是动态生成的字节码不会以.class文件的形式保存在硬盘上,所以我们称作动态代理。
            
            //第一个参数是类装载器:JVM会在内存中自动生成一个字节码,但是这个字节码要想运行,必须经过类装载器的装载
            //然后进一步解析,所以必须传递一个类装载器,这个类装载器就是用来装载这个临时的“字节码”。
            //代理类和目标类必须使用同一个类装载器。
            
            //第二个参数:是JVM在生成代理类的时候需要实现接口,但是这个接口又不能随便写,因为代理类和目标类要求实现相同的接口。
            //所以我们将目标类实现的接口获取到之后传递过来就行了。
            //JDK中提供的代理模式只能代理接口。如果目标类它的父类型不是一个接口而是一个抽象类,那么JDK中提供的动态代理就不能用了,需要使用
            //第三方组件,例如:cglib。
            
            //第三个参数:是InvocationHandler,这是一个接口,这个接口中的方法会在代理类调用代理方法的时候自动执行。
            IDB dbProxy = (IDB)Proxy.newProxyInstance(db.getClass().getClassLoader(), db.getClass().getInterfaces(), new TimeInvocationHandler(db));
            
            
            //通过代理对象中的方法去执行目标对象中的方法。
            dbProxy.insert(); //dbProxy是一个动态生成的代理对象,由于这个代理对象实现了和OracleDB一样的接口,所以可以用IDB接口指向JVM中的代理对象。
            dbProxy.delete(); // 这里调用的delete方法是是代理类中的代理方法,不是目标类中的目标方法。但是一定会通过代理方法去调用目标方法。
            dbProxy.update();
            
        }
    
    }

      

  • 相关阅读:
    C# 中的委托和事件
    C# 托管资源和非托管资源
    .NET Core 2.0
    PyQt5教程——事件和信号(5)
    PyQt5教程——布局管理(4)
    PyQt5教程——菜单和工具栏(3)
    PyQt5教程——第一个程序(2)
    PyQt5教程——介绍(1)
    如何通过 GitLab 进行在Azure WebApp中持续部署
    如何检测 Azure Web 应用沙盒环境文件系统存储量
  • 原文地址:https://www.cnblogs.com/yangyanbo/p/12370110.html
Copyright © 2020-2023  润新知