首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Java中的署理的使用

2013-12-26 
Java中的代理的使用public interface Person {public void say()}??? ?建立一个接口的实现类:public clas

Java中的代理的使用
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.jarpublic 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();    }}输出:中国我是-中国-人我是*中国*人我是#中国#人我是#中华人民共和国#人

?

1 楼 lancecong 昨天   写的不错,容易理解!顶。 2 楼 koybe 20 小时前   浅显易懂,赞一个 3 楼 jiakechong 19 小时前   第3种代理还没用过 4 楼 antique 18 小时前   写的很明了,学习了。

热点排行