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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 彭盼 中级黑马   /  2012-6-8 17:48  /  1845 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  Collection proxy= (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(),new Class[] {Collection.class},
    new InvocationHandler() {
                   @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                     throws Throwable {
                  
            }
   
    });
构造函数中的前两个参数为什么是collection接口的加载器和collection接口的字节码文件
而加入目标类后:

private static Object getProxy(final Object target,final Advice advice) {
                Object proxy3 = Proxy.newProxyInstance(
                                target.getClass().getClassLoader(),
                                /*new Class[]{Collection.class},*/
                                target.getClass().getInterfaces(),
                                new InvocationHandler(){
后面的代码省略了,
在加入了目标类后,为什么参数中的加载器和字节码数组都变成目标类了

2 个回复

倒序浏览
本帖最后由 李文富 于 2012-6-8 20:45 编辑

Proxy.newProxyInstance(loader, interfaces, h)
         Loader():要代理的函数名获得它的加载器;
         interfaces:要代理的函数的参数,是接口

         h(handler):实现了InvocationHandler接口的对象,该类中要实现invoke()方法

1、  创建实现类Collection接口的动态类和查看其名称

2、  编码列出动态类中的所有构造方法和参数名

3、  编码列出动态类所以方法和参数签名

4、  创建动态类的实例对象

>使用反射获得构造方法

>编写一个lnvocationHandler类

>调用构造方法创建动态类的实例对象,并编写lnvocationHandler类的实例对象传入

>打印创建的对象和调用对象的没有返回值的方法和getClass方法
//代理3
Collention proxy3 = (Collention) proxy.newProxyInstance(
              collention.class.getClassLoader(),
              new Class[] (Collention.class),
              new InvocationHandler(){
                        ArrayList target = new ArrayList();
                        public Object invoke(Object proxy, Method method,Object[] args)throws Throwable
                             {
                                  //ArrayList target = new ArrayList();
                                   long beginTime = System.currentTimeMillis();
                                   Object retVal = method.invoke(target,args);
                                   long endTime = System.currentTimeMillis();
                                   SOP(method.getName()+”running time”+endTime-beginTime)
                                   return retval;
                                  //return method.invoke(proxy,args);//死循环
   }}
);
-------------------------------------

1、  工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换,其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean.则直接返回该类的实例对象,否则返回该类实例对象的getProxy方法返回的对象。

2、  BeanFactory的构造方法接受代表配置文件的输入流对象,配置文件格式如下
       #xxx=java.util.ArrayList

xxx= cn.itcast.ProxyFactoryBean

xxx.target=java.util.ArrayList

xxx.advice=cn.itcast.MyAdvice

3、  proxyFacotryBean充当封装生成动态代理的工厂,需要为工厂类提供配置参数信息 : 目标,通知

4、  编写客户端应用:编写实现Advice接口的类和在配置文件中进行配置,调用BeanFactory获取对象

//定义代理类封装ProxyFactoryBean.class对象

import java.lang.reflect.*;

public class ProxyFactoryBean

{

  private Advice advice;

  private Object target;

  Object proxy3 = proxy.newProxyInstance(

         target.class.getClassLoader(),

         target.getClass().getInterfaces(),

         new InvocationHandler(){

             public Object invoke(Object proxy, Method method,Object[] args)throws Throwable

                 {

                       Advice.beforeMethod(method);

                       Object retVal = method.invoke(target,args);

                       Advice afterMethod(method);

                       return retval;

                       }}

                 );

         return proxy3;

}


回复 使用道具 举报
构造函数中的前两个参数为什么是collection接口的加载器和collection接口的字节码文件-----因为这里就指明了要代理的目标是哪些接口,动态代理是使用反射的方式产生代理实例的,当然就要通过类加载器加载字节码文件,所以必须是指定接口的类加载器,这样就保证了加载出来的是同类型的class对象,我们知道不同的类加载器加载同一份字节码产生的class对象是不一样的。


后面的加入目标类之后就是代理类改变了代理的目标,也就是说我们需要代理什么样的接口或目标类需要在创建代理实例对象时就指定,这样你也就明白一个代理类实例只能代理创建时传入构造的接口或目标
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马