zoukankan      html  css  js  c++  java
  • 使用Jdk实现动态代理

    一)、创建动态代理的步骤

    1、主题接口

    2、代理类

    3、真实类

    4、使用类

    1)主体接口中定义了代理类和真实类的的公共接口方法,代理类和真实类分别实现主体接口,真实类实现了接口方法的具体逻辑,代理类也实现了同样的接口方法,在方法中调用真实类的逻辑,相当于拿到了被代理人的授权,执行被代理人拥有的功能。

    2)在实用类中,利用java的多态特性,使用公共接口,接收代理类,接收代理类对象,使用代理类调用公共方法,实现真实类的具体逻辑。

    二)、使用jdk实现动态代理

    一、为什么要使用动态代理?

    1)、原有的静态代理一个接口对应一个代理类,当真实主题很多时,要写多个代理类

    2)、当接口有变动时,真实类和代理类都要变动。使用了动态代理,代理类是动态的生成的,代理类动态的实现公共接口的方法

    二、步骤

    1、主题接口

    2、真实类

    3、InvocationHanlder接口的实现类

    Proxy.newInstance(ClassLoader loader, class<?>[] inteface, 			InvocationHander hanlder)   //创建一个代理实例
    
    	invoke(Object proxy, Method method, args)//代理类的实现逻辑
    

    4、使用类

    三)、使用动态代理实现数据库查询的延迟加载

    主题接口:

    /**
     * 数据库查询的公共接口
     */
    public interface DBQueryInterface {
        public String request();
    }
    

    真实类:

    public class DBQuery implements DBQueryInterface{
        /**
         * 模拟重量级对象,对象初始化时需要进行数据库连接
         */
        DBQuery(){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        /**
         * 数据库查询的具体逻辑实现
         * @return
         */
        @Override
        public String request() {
            return "我正在执行数据库查询操作";
        }
    }
    

    动态代理类:

    public class DBQueryJdkProxy implements InvocationHandler {
        DBQuery dbQuery = null;
        /**
         * 获取代理对象
         */
        public Object bind(){
            return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{DBQueryInterface.class}, new DBQueryJdkProxy());
        }
    
        /**
         * invoke方法是代理逻辑的具体实现
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if(dbQuery == null){
                //延迟加载,当使用到时才创建重量级对象
                dbQuery = new DBQuery();
            }
           return dbQuery.request();
        }
    }
    

    使用类:

    public class Client {
        public static void main(String[] args) {
            //初始化时先加载代理对象
            DBQueryInterface JdkProxy= (DBQueryInterface) new DBQueryJdkProxy().bind();
            //使用时才创建真实的对象
            String result = JdkProxy.request();
            System.out.println(result);
        }
    }
    

    结果:

    我正在执行数据库查询操作
    

    改进: 使用动态代理实现延迟加载同时增强原有类的功能

    主题接口:

    /**
     * 数据库查询的公共接口
     */
    public interface DBQueryInterface {
        public String request();
    }
    

    真实类:

    public class DBQuery implements DBQueryInterface{
        /**
         * 模拟重量级对象,对象初始化时需要进行数据库连接
         */
        DBQuery(){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        /**
         * 数据库查询的具体逻辑实现
         * @return
         */
        @Override
        public String request() {
            return "我正在执行数据库查询操作";
        }
    }
    

    动态代理类:

    /**
     * 使用动态代理创建数据库查询的代理对象
     * 1、实现InvocationHandler接口
     * 2、调用Proxy.newInstance()动态的创建代理对象
     */
    public class DBQueryJdkProxy implements InvocationHandler {
        Object target;
        /**
         * 获取代理对象
         */
        public Object bind(Object target){//target是真实类对象,给给定的真实类对象创建一个代理,由代理去完成真实类的工作
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        /**
         * 增强原有类的功能
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("事物开始");
            System.out.println(method.invoke(target, args));
            System.out.println("事物结束");
            return null;
        }
    }
    

    使用类:

    public class Client {
        public static void main(String[] args) {
            //加载数据库查询代理工厂
            DBQueryJdkProxy dbQueryJdkProxy = new DBQueryJdkProxy();
            //给指定的对象创建代理工厂
            DBQueryInterface proxy = (DBQueryInterface) dbQueryJdkProxy.bind(new DBQuery());
            proxy.request();
        }
    }
    金麟岂能忍一世平凡 飞上了青天 天下还依然
  • 相关阅读:
    android29
    android28
    android27
    android26
    Dynamics CRM2011 MspInstallAction failed when installing an Update Rollup
    Dynamics CRM Import Solution Attribute Display Name description is null or empty
    The service cannot be activated because it does not support ASP.NET compatibility
    IIS部署WCF报 无法读取配置节“protocolMapping”,因为它缺少节声明
    Unable to access the IIS metabase.You do not have sufficient privilege
    LM算法与非线性最小二乘问题
  • 原文地址:https://www.cnblogs.com/Auge/p/11579271.html
Copyright © 2011-2022 走看看