《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+"------------\n");
    }
}

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------------

posted @ 2019-06-22 11:30  山枫叶纷飞  阅读(417)  评论(0编辑  收藏  举报