当前位置:首页 > 开发 > 编程语言 > Java > 正文

Java中的代理的使用

发表于: 2013-12-24   作者:dyy_gusi   来源:转载   浏览次数:
摘要: Java中的代理代理解释:一种设计模式,代理类与委托类(被代理对象、目标对象)有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 通俗解释:不直接调运目标对象,直接调运代理对象,让代理对

Java中的代理
代理解释:一种设计模式,代理类与委托类(被代理对象、目标对象)有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
通俗解释:不直接调运目标对象,直接调运代理对象,让代理对象去调运目标对象。
代理目的:当调运代理对象,然后在代理对象调运目标对象之前或者调运目标对象以后,我们可以干一些事,比如权限控制,日志记录等。
代理分类:静态代理,动态代理
举例分析:

    程序说明:有刚学说话的个小朋友想说“我是中国人”,但是他不能完整的说出来,只能说“中国”两个字,那么我们就使用代理模式,让他的爸爸妈妈帮他把他想说的话补充完整。他的爸爸帮他说:“我是”,他的妈妈帮他说:“人”。然后即使小朋友只说了“中国”,但是我们听见的就是“我是中国人”。

    这其中小朋友就是被代理对象、目标对象,他的爸爸妈妈就是代理对象。
    首先建立一个Person接口:

public interface Person {
    public void say();
}

 
    建立一个接口的实现类:

public class PersonImpl implements Person {
    @Override
    public void say() {
        System.out.print("中国");
    }
}

 
    再建立一个没有实现接口的类:

public class PersonNoImpl {
    public void say() {
        System.out.print("中华人民共和国");
    }
}

 

    1.静态代理:在程序运行前,代理类的.class文件就已经存在了。

public class PersonProxy implements Person {
    private Person person;// 被代理对象

    public PersonProxy(Person p) {
        this.person = p;
    }

    @Override
    public void say() {
        System.out.print("我是-");
        person.say();// 在目标方法前后分别添加操作
        System.out.println("-人");
    }

}

    这种方式的最大缺点就是每次我们都需要建立不同的代理对象,灵活性和可复用性都很差,所以我们需要使用到动态代理技术。

    2.动态代理:在程序运行时,运用反射机制动态创建而成。
        有两种实现方式:JDK代理,CGLIB代理
        方式1:使用jdk提供的代理对象(代理对象需要实现InvocationHandler接口,目标对象必须实现其他接口)

public class PersonProxyJdk implements InvocationHandler {
    private Object targetObj;

    /**
     *
     * @param obj
     *            被代理对象
     * @return 代理对象的实例
     */
    public Object createProxyInstance(Object obj) {
        this.targetObj = obj;
        /*
         * 参数说明 参数一:ClassLoader,定义代理类的类加载器
         * 参数二:Class<?>,代理类要实现的接口列表
         * 参数三:InvocationHandler,指派方法调用的调用处理程序 (指定调运哪个类的invoke方法)
         */
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), this.targetObj.getClass().getInterfaces(), this);
    }

    /*
     * 当代理对象的方法被调运时,就会执行回调函数invoke方法,让这个回调函数再去执行目标代码的指定方法,
     * 并且会将代理对象接收到的参数传递给目标代码。 这是一个回调函数。
     * 注意:method args 都是由调运代理对象后产生的。所以是确定的。
     * 还可以在这个回调函数中做一些手脚,比如限制调运或者其他。
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        System.out.print("我是*");
        result = method.invoke(targetObj, args);
        System.out.println("*人");
        return result;
    }

}    

            注意:目标对象必须实现接口。因为需要得到接口的所有方法,然后进行调运接口的所有方法。
            
        方式2:使用cglib提供的代理对象(代理对象需要实现MethodInterceptor接口,目标对象不需要实现接口)

//导包:cglib-nodep-2.2.3.jar
public class PersonProxyCglib implements MethodInterceptor {
    private Object targetObj;

    /**
     * 生成的代理对象其实就是目标对象的子类
     * @param obj
     *            被代理对象
     * @return 代理对象的实例
     */
    public Object createProxyInstance(Object obj) {
        this.targetObj = obj;
        Enhancer enhancer = new Enhancer();// 用于生成代理对象
        enhancer.setSuperclass(this.targetObj.getClass());// 设置代理对象的父类
        enhancer.setCallback(this);// 设置代理对象的回调函数就是本生
        return enhancer.create();// 生成代理对象
    }

    /*
     * 当代理对象的方法被调运时,就会执行改代理对象的回调函数,也就是intercept方法 这个回调函数接收代理对象传递来的参数
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        Object result = null;
        System.out.print("我是#");
        result = proxy.invokeSuper(obj, args);
        System.out.print("#人");
        return result;
    }

}

            注意:目标对象不须实现接口。因为生成的代理对象时目标对象的子类。
        
    3.测试上面的代理

public class Main {
    public static void main(String[] args) {

        Person zhangsan = new PersonImpl();// 被代理的对象

        zhangsan.say();// 如果让代理目标直接执行目标方法,就不能在目标方法前后操作
        System.out.println();

        PersonProxy proxy = new PersonProxy(zhangsan);// 将被代理的对象传递一个代理类
        proxy.say();// 让代理类去执行目标方法,这个时候代理类就在目标方法执行前后乱搞了

        PersonProxyJdk proxyJdk = new PersonProxyJdk();// 创建一个代理对象
        Person zhangsanJdk = (Person) proxyJdk.createProxyInstance(zhangsan);// 将被代理对象传递给代理对象,并且返回被代理接口
        zhangsanJdk.say();// 调运被代理对象的接口,就能动态的去执行代理对象想要执行的操作

        PersonProxyCglib proxyCglib = new PersonProxyCglib();// 创建Cglib代理对象
        Person zhansanCglib = (Person) proxyCglib.createProxyInstance(zhangsan);// 将被代理对象传递给代理对象,并且返回被代理接口
        zhansanCglib.say();// 调运被代理对象的接口,就能动态的去执行代理对象想要执行的操作
        
        // 使用Cglib的时候,目标对象可以不实现任何接口,但是使用JDK代理的时候就不可以
        PersonNoImpl lisi = new PersonNoImpl();
        PersonNoImpl lisiCglib = (PersonNoImpl) proxyCglib.createProxyInstance(lisi);
        lisiCglib.say();

    }
}
输出:
中国
我是-中国-人
我是*中国*人
我是#中国#人
我是#中华人民共和国#人

 

Java中的代理的使用

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
一、代理的概念与作用 生活中的代理 武汉人从武汉的代理商手中买联想电脑和直接跑到北京传智播客旁
动态代理在Java中是很重要的一部分,在很多框架中都会用到,如Spring中的AOP、Hadoop中的RPC等。为
一. 前言: 在 上一篇博文中, 我们使用模板模式进行事务管理, 代码看起来已经很简洁了, 但是还是不太
有时候我们会碰到需要设置代理,然后通过svn获取源代码,下面我们来看一下如何设置; 1、找到 C:\Do
有时候我们会碰到需要设置代理,然后通过svn获取源代码,下面我们来看一下如何设置; 1、找到 C:\Do
java中的代理按照代理类的生成时期不同分为静态代理和动态代理。 (1)静态代理。由程序员创建或由
代理模式UML类图 代理模式 1. 静态代理 /** * 为被代理的类提供一个接口,是为了提高代理的通用性,
一、代理类 代理类的概念与作用: 1、 作用: 要为已存在的多个具有相同接口的目标类的各个方法增加
Java动态代理一——动态类Proxy的使用 1.什么是动态代理? 答:动态代理可以提供对另一个对象的访问
1.Proxy 模式 代理模式支持将某些操作从实际的对象中分离出来,通过它的代理类提供处理。这样便于修
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号