zoukankan      html  css  js  c++  java
  • 《Java设计模式》之代理模式 -Java动态代理(InvocationHandler) -简单实现

    如题

    • 代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
    • 代理模式类图
    • 代理模式可细分为如下, 本文不做多余解释
    • 远程代理
    • 虚拟代理
    • 缓冲代理
    • 保护代理

    借鉴文章

    https://www.cnblogs.com/java-my-life/archive/2012/04/23/2466712.html
    《Java设计模式》 -Java动态代理(InvocationHandler)

    AbstractUserDAO 抽象的用户DAO类, 抽象主题角色

    package proxy;
    
    /**
     * @description  抽象的用户DAO类, 抽象主题角色
     * @Date 2019/6/22 10:05
     */
    public interface AbstractUserDAO {
         Boolean findUserById(Long userId);
    }
    
    

    UserDAO 用户DAO类,具体主题角色

    package proxy;
    
    /**
     * @description 类的详细说明: 用户DAO类,具体主题角色
     * @Date 2019/6/22 10:08
     */
    public class UserDAO implements AbstractUserDAO{
        /**
         * 简单举个栗子,实际应用时自行调整
         * @param userId
         * @return
         */
        @Override
        public Boolean findUserById(Long userId) {
            Long maxx =new Long( "10000000");
            if(userId>=1 && userId<=maxx){
                System.out.println("查询ID为 "+userId+" 的用户信息成功!");
                return true;
            }else{
                System.out.println("查询ID为 "+userId+" 的用户信息失败");
                return false;
            }
    
        }
    }
    

    DAOLogHandler 自定义请求处理程序, 前后打印日志

    package proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    
    /**
     * @description  自定义请求处理程序,实现前置和后置通知, 及前后打印日志
     * @Date 2019/6/22 10:15
     */
    public class DAOLogHandler implements InvocationHandler {
        /**calendar 属性用于打印时间*/
        private Calendar calendar;
        private Object object;
    
        /**
         * 自定义有参构造器,用以注入一个需要提供代理的真实主题对象
         * @param object 代理对象
         */
        public DAOLogHandler(Object object) {
            this.object = object;
        }
    
        /**
         * @param proxy 需要代理的类
         * @param method 需要代理的方法
         * @param args 代理方法的参数数组
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            beforeInvoke();
            /**转发调用*/
            Object result = method.invoke(object,args);
            afterInvoke();
            return result;
        }
        /**
         * 实现前置通知处理
         */
        private void beforeInvoke(){
            //使用当前时间构造默认的<code>GregorianCalendar类</code> ,在默认时区, 使用默认值
            calendar = new GregorianCalendar();
            int hour = calendar.get(Calendar.HOUR_OF_DAY);
            int minute = calendar.get(Calendar.MINUTE);
            int second = calendar.get(Calendar.SECOND);
            System.out.println("------------调用时间 "+hour+":"+minute+":"+second+"------------");
        }
        /**
         * 实现后置通知处理
         */
        private void afterInvoke(){
            calendar = new GregorianCalendar();
            int hour = calendar.get(Calendar.HOUR_OF_DAY);
            int minute = calendar.get(Calendar.MINUTE);
            int second = calendar.get(Calendar.SECOND);
            System.out.println("------------调用方法结束 "+hour+":"+minute+":"+second+"------------
    ");
        }
    }
    
    

    Client 主要测试类

    package proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    /**
     * 客户端类, 主要测试类
     *
     * 题目描述: 某公司要为公司的OA(办公自动化)系统的数据访问层DAO增加方法调用日志,
     *          记录每一个方法被调用的时间和调用结果,现使用动态代理(InvocationHandler)进行设计和实现.
     */
    public class Client {
        public static void main(String[] args) {
            InvocationHandler handler = null;
    
            AbstractUserDAO userDAO = new UserDAO();
            /**初始化调用处理器*/
            handler = new DAOLogHandler(userDAO);
    
            AbstractUserDAO proxy=null;
    
            //动态创建代理对象
            // Proxy.newProxyInstance : 返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。
            proxy = (AbstractUserDAO) Proxy.newProxyInstance(AbstractUserDAO.class.getClassLoader(),
                    new Class[]{AbstractUserDAO.class},handler);
            proxy.findUserById((long)001);
            proxy.findUserById((long)999999999);
        }
    }
    
    

    测试输出

    
    ------------调用时间 10:59:25------------
    查询ID为 1 的用户信息成功!
    ------------调用方法结束 10:59:25------------
    
    ------------调用时间 10:59:25------------
    查询ID为 999999999 的用户信息失败
    ------------调用方法结束 10:59:25------------
    
    
  • 相关阅读:
    Angularjs中添加ckEditor插件
    Angularjs中添加HighCharts
    ngTbale真分页实现排序、搜索等功能
    移动端小功能杂记(三)
    Html5 history Api简介
    移动端流程页处理
    Html5离线缓存简介
    多Tabs的横向滚动插件(支持Zepto和jQuery)
    flutter从零开始第一篇-环境搭建(Windows)
    vue 父子组件与全局数据传递共享
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/11068254.html
Copyright © 2011-2022 走看看