23种设计模式之代理模式

来源:互联网 发布:加密锁软件下载 编辑:程序博客网 时间:2024/06/01 09:31

代理模式:即Proxy Pattern,23种常用的面向对象软件的设计模式之一。

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式能够解决什么问题呢?

1、监听被代理的类里面的方法什么时候执行
2、动态的给某一个方法添加新的功能

代理模式分类:
静态代理

能够使用静态代理首先得有一个前提条件:被代理的类必须要实现接口。
实现步骤:
(1)、首先要被代理类要实现接口
(2)、代理类必须要和 被代理的类实现相同的接口
(3)、在我们的代理类中实例化我们的被代理类的对象
(4)、重写接口中的方法
(5)、在我们调用被代理类中的方法的时候 可以进行拓展了
接口类 IUserDao.java

public interface IUserDao {    public  void  method1();}

被代理类:UserDao.java

public class UserDao implements IUserDao {    @Override    public void method1() {        // TODO Auto-generated method stub        System.out.println("这是方法1");    }}

代理类:UserDaoProxy

public class UserDaoProxy implements IUserDao {    private UserDao userDao;    @Override    public void method1() {        // TODO Auto-generated method stub        System.out.println("开启事物");        userDao.method1();        System.out.println("结束事物");    }    public UserDaoProxy(UserDao userDao) {        super();        this.userDao = userDao;    }    public UserDaoProxy() {        this.userDao =new UserDao();    }}

动态代理

动态代理 又名JDK代理,也就是说这种代理模式是在JDK中提供了相应的实现类。动态代理的原理生成了子类的对象,可以避免静态代理中代理类接口过多的问题。
动态代理也有一个前提:就是我们被代理的类也要实现接口(或者本身就是接口)。
代码实现
接口和被代理类和上面的一样
测试类:Test.java

 public static void main(String[] args) {        // TODO Auto-generated method stub        UserDao userDao=new UserDao();        //在JDk中提供了一个类  这个类  Proxy        /**         * 第一个参数:就是当前代理的类的class对象.getClassLoader         * 第二个参数:如果被代理的是类 class对象.getInterfaces()         * 第二个参数如果代理的是接口的话 那么应该这样写 new Class[]{代理接口.class}         * 第三个参数:就是用来监听我们的代理类里面方法的执行的         */        IUserDao userDao2=(IUserDao) Proxy.newProxyInstance(UserDao.class.getClassLoader(), UserDao.class.getInterfaces(), new InvocationHandler() {        /**        * 中断我们的方法的执行的        * 你可以这样理解 就是调用我们的被代理类里面的方法的时候会自动被拦截下来  你可以确定是否执行        * proxy:生成的代理对象        * method:当前你请求的方法(反射里面的)        * args:这个就是你执行这个方法需要的参数        */            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                //申明一个返回值                Object returnValue=null;                //下面就可以对你要监听的方法进行处理                //例如:判定我们执行的方法是不是method1()方法                String methodName=method.getName();                if("method1".equals(methodName)){                    //是不是要在执行方法之前添加事务                    System.out.println("打开事务");                    //执行这个方法 第一个参数;就是被代理的这个对象                    returnValue=method.invoke(userDao, args);                    //在方法执行之后 关闭事务                    System.out.println("关闭事务");                }else{  //这个表示的是当前请求的不是save方法                    //下面表示的是没有调用save这个方法                    returnValue=method.invoke(userDao, args);                   }                return returnValue;            }        });        //查看userDao2的结果        userDao2.method1();    }

cglib代理

这种代理方式需要导入包
cglib-2.2.2.jar
asm-3.3.1.jar

UserDao.java

public class UserDao {    public void test(){        System.out.println("数据保存成功...");    }}

UserDaoProxy.java

public class UserDaoProxy {    private UserDao userDao=null;    public UserDaoProxy() {        userDao=new UserDao();    }    public UserDaoProxy(UserDao userDao) {        this.userDao=userDao;    }    /*     * 该方法返回被代理对象     */    public Object getObject() {        //第一步:申明这个enhancer对象        Enhancer enhancer=new Enhancer();        //第二步:设置该代理类的对象的父类        enhancer.setSuperclass(userDao.getClass());        //设置监听父类里面的方法的回调        enhancer.setCallback(new MethodInterceptor() {            @Override            public Object intercept(Object obj, Method method, Object[] arg2,MethodProxy arg3) throws Throwable {                //获取方法名                String methodName = method.getName();                //设置返回的结果                Object returnValue=null;                //判定是否是我们的监听的方法                if("test".equals(methodName)) {                    System.out.println("执行事务");                    returnValue=method.invoke(userDao, arg2);                    System.out.println("结束事务");                }else {                    //如果不是,就直接放行                    returnValue=method.invoke(userDao, arg2);                }                return returnValue;            }        });        return enhancer.create();       }}

还可以写成这样

public class UserDaoProxy implements MethodInterceptor{    private UserDao userDao=null;    public UserDaoProxy() {        userDao=new UserDao();    }    public UserDaoProxy(UserDao userDao) {        this.userDao=userDao;    }    public Object getObject() {        //声明一个enhancer对象        Enhancer enhancer=new Enhancer();        //设置UserDao为该代理对象的父类        enhancer.setSuperclass(userDao.getClass());        //监听父类的方法        enhancer.setCallback(this);        return enhancer.create();    }    //监听方法    @Override    public Object intercept(Object obj, Method method, Object[] arg2,MethodProxy arg3) throws Throwable {        //获取方法名        String methodName = method.getName();        //返回结果        Object returnValue=null;        //判定方法是否是我们监听的方法        if("test".equals(methodName)) {            System.out.println("开始事务");            returnValue=method.invoke(userDao, arg2);            System.out.println("结束事务");        }else{            returnValue=method.invoke(userDao, arg2);        }        return returnValue;    }}

测试类

public static void main(String[] args) {        // TODO Auto-generated method stub        UserDaoProxy userDaoProxy=new UserDaoProxy(new UserDao());        UserDao userDao=(UserDao) userDaoProxy.getObject();    }
原创粉丝点击