A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© tfy 中级黑马   /  2013-1-3 23:41  /  1840 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

什么是动态代理
分类: 评论(2) 举报


import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;


/**
* 代理模式至少需要实现两个类,一个代理类,一个被代理类(都要实现共有接口)。
* 动态代理之所以称为动态,是因为代理类在运行时由Proxy类产生,
* 这就大大减少了需要我们手工设计代理类的数量。
*在实际应用中,Proxy通过类装载器和需要实现的接口来产生代理类,
*即Proxy.getProxyClass(ClassLoader, Class[]),返回为代理类的Class实例。
*一般而言,该方法由InvocationHandler的实现类中的方法来调用,
*可以取这样的名字:getProxyObject,该方法使用Proxy.getProxyClass后
*(此时两个入口参数可以用realObject.getClass.getClassLoader()
*以及realObject.getClass.getInterfaces()两个方法得到,
*realObject指被代理类实例,一般由InvocationHandler的实现类的构造函数注入),
*进一步使用Class中的getConstructor(new Class[] { InvocationHandler.class}).newInstance(new Object[] { this })
*来得到代理类的实例(或者合并这两个方法,
*用Proxy.newProxyInstance(realObject.getClass.getClassLoader(), realObject.getClass.getInterfaces(),this)方法)
*。但是必须注意代理类的实现是由Proxy完成,与InvocationHander的实现类毫无关系,
*InvocationHander的实现类只是通过代理类的构造函数注入后实现了对代理类中方法调用的拦截。
*InvocationHander的实现类需要保留一个指向被代理类的引用(或称句柄、指针),
*该被代理类一般通过InvocationHandler的实现类的构造函数注入,也可以用set方法,
*一般可以取为realObject。则在InvocationHandler接口的invoke方法中,
*对于realObject中相应方法的直接调用是用method.invoke(realObjet, args )实现的,
*其中method和args直接由invoke方法中的输入参数给出。
*
*好了先让我们俩了解什么是代理
*/

//AOP面向切面的编程
public class BeanFactory {
    //动态代理入门
    public static void main(String[] args) throws Exception {
        //首先我们先让JVM生成一个代理类
        Class clazzProsy = Proxy.getProxyClass(Collection.class
                .getClassLoader(), Collection.class);
        System.out.println(clazzProsy.getName());

        System.out.println("-----Begin constructor-----");
        //得到代理类上的构造函数
        Constructor[] constructors = clazzProsy.getConstructors();
        for (Constructor constructor : constructors) {
            String name = constructor.getName();
            // 单线程下StringBuilder效率比较高
            // 多线程时StringBuffer效率比较高
            StringBuilder strB = new StringBuilder(name);
            strB.append('(');
            Class[] clazzParams = constructor.getParameterTypes();
            for (Class clazzParam : clazzParams) {
                strB.append(clazzParam.getName()).append(',');
            }
            if (clazzParams.length != 0 && clazzParams != null)
                strB.deleteCharAt(strB.length() - 1);
            strB.append(')');
            System.out.println(strB.toString());
        }

        System.out.println("-----Begin methods-----");
        //得到代理类上的所有方法
        Method[] methods = clazzProsy.getMethods();
        for (Method method : methods) {
            String name = method.getName();
            // 单线程下StringBuilder效率比较高
            // 多线程时StringBuffer效率比较高
            StringBuilder strB = new StringBuilder(name);
            strB.append('(');
            Class[] clazzParams = method.getParameterTypes();
            for (Class clazzParam : clazzParams) {
                strB.append(clazzParam.getName()).append(',');
            }
            if (clazzParams.length != 0 && clazzParams != null)
                strB.deleteCharAt(strB.length() - 1);
            strB.append(')');
            System.out.println(strB.toString());
        }
        
        
    }
}


1 个回复

倒序浏览
1. Overview
    Java在java.lang.reflect包下,定义了自己的代理。利用这个包下的类,我们可以在运行时动态地创建一个代理类,实现一个或多个接口。并将方法的调用转发到你所指定的类。因为实际代理是在运行时创建的,所以称为:动态代理。

    Proxy:完全由java产生的,而且实现了完整的subject接口。
    InvocationHandler:Proxy上的任何方法调用都会被传入此类,InvocationHandler控制对RealSubject的访问。
    因为Java已经帮助我们创建了Proxy类,我们需要有办法告诉Proxy类你要做什么,我们不能像以前一样把代码写入到Proxy类中,因为 Proxy类不是我们实现的。那么我们应该放在哪里?放在InvocationHandler类中,InvocationHandler类是响应代理的任何调用。我们可以吧InvocationHandler想成是代理收到方法调用后,请求做实际工作的对象。
     2. java.lang.reflect.InvocationHandler
    被代理实例所实现的一个接口,内部只有一个invoke()方法,签名如下;
    Java代码
    public Object invoke(Object proxy, Method method, Object[] args)
    当代理的方法被调用的时候,代理就会把这个调用转发给InvocationHandler,也就会调用它的invoke()方法。
    3. java.lang.reflect.Proxy
    提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类,我们经常使用的静态方式是:
    Java代码
    newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)




Java代码  
1.package com.jelly.dynamicproxy;  
2.  
3.import java.lang.reflect.InvocationHandler;  
4.import java.lang.reflect.Method;  
5.import java.lang.reflect.Proxy;  
6.import java.util.List;  
7.import java.util.Vector;  
8.  
9./**
10. * 动态代理
11. *  
12. * @author Jelly QQ136179492
13. *  
14. */  
15.public class VectorProxy implements InvocationHandler {  
16.    private Object object;  
17.  
18.    public VectorProxy(Object obj) {  
19.        this.object = obj;  
20.    }  
21.  
22.    public Object invoke(Object proxy, Method method, Object[] args)  
23.            throws Throwable {  
24.        System.out.println("before calling:" + method);  
25.        // 当有参数的时候,打印出所有方法  
26.        if (null != args)  
27.            for (Object ob : args) {  
28.                System.out.println(ob);  
29.            }  
30.        Object obj = method.invoke(object, args);  
31.        System.out.println("after calling:" + method);  
32.        return obj;  
33.    }  
34.  
35.    public static Object factory(Object obj) {  
36.        Class<?> classType = obj.getClass();  
37.        for (Class c : classType.getInterfaces()) {  
38.            System.out.println("接口" + c.getName());  
39.        }  
40.        // 返回动态代理  
41.        return Proxy.newProxyInstance(classType.getClassLoader(),  
42.                classType.getInterfaces(), new VectorProxy(obj));  
43.    }  
44.  
45.    public static void main(String[] args) {  
46.        List v = (List) factory(new Vector());  
47.        System.out.println(v.getClass().getName());  
48.        v.add("new");  
49.        v.add("york");  
50.    }  
51.}  


回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马