• 使用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();
        }
    }
    金麟岂能忍一世平凡 飞上了青天 天下还依然
  • 相关阅读:
    如何在eclipse开发环境中连接数据库?oracle和db2
    oracle数据库表的记录误删后如何恢复
    人事经理眼中的好简历
    JavaScript常用方法
    如何解决plsql被用户锁定的问题?
    eclipse 快捷键
    刚开始用9.3的版本,一堆问题。(转)
    十条不错的编程观点(转)
    http://localhost:8099无法登录,出现incorrect info报错信息,怎么办?
    http://localhost:8399/arcgis/rest/services 无法访问,怎么办?
  • 原文地址:https://www.cnblogs.com/Auge/p/11579271.html
Copyright © 2020-2023  润新知