黑马程序员_代理

来源:互联网 发布:java list 合并去重 编辑:程序博客网 时间:2024/05/18 19:19

------- 物联云培训java培训、期待与您交流! ----------  

概念:实际上就是要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能。

代理的作用:实际上就是在你的目标代码上,添加一些别的代码,你本身的代码也运行了。

            这个新的代码就是代理。

代理类的好处:生成代理类后但你想要改变程序是不需要改变源程序。

交叉业务的编程问题即面向方面的编程(AOP),AOP的目标就是使交叉业务模块化,可以采用将切面代理移动到原始方法的周围,这与直接在方法中编写切面代理的过程效果是一样的。

实际上是面向一个面的,在一些目标方法的前后位置插入一些代码。

 动态代理技术
概述:
    1、要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,
       这时就不能采用静态代理方式,需用动态代理技术。
      注意:JVM生成的动态类必须实现一或多个接口,所以JVM生成的动态代理类只能用作具有相同接口的目标类代理。
    CGLIB库可以动态生成一个类的子类,一个类的子类也可以作为该类的代理,
     所以,如果要为一个没有实现接口的类生成动态代理,那么可以使用CGLIB库

创建一个动态类:

Proxy:代理类

//得到一个类的class

Class clazz=

proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class)

这个代理类只有一个构造方法:

$proxy0(InvocationHandleri);

InvocationHandler是一个接口

//获取构造函数

Constructor constructor=clazz.getConstructor(InvocationHandler.class);

创建动态类的实例对象方式一

class MyInvocationHander1 implements InvocationHandler{          public Objectinvoke(Object proxy, Method method, Object[] args)                  throwsThrowable {              // TODOAuto-generated method stub              return null;          }      }

创建动态类的实例对象方式二

Collection proxy2 = (Collection)constructor.newInstance(newInvocationHandler(){          public Objectinvoke(Object proxy, Method method, Object[] args)                  throwsThrowable {              return null;          }      });

获得对象

Collection proxy1 =(Collection)constructor.newInstance(new MyInvocationHander1());      System.out.println(proxy1);      proxy1.clear();proxy1.size();

注意:不能调用有返回值的size方法,因为:size的返回int类型的,代码中是返回的null,null没有办法转变成int

//可以直接创建对象:Object proxy3 = Proxy.newProxyInstance(               target.getClass().getClassLoader(),               target.getClass().getInterfaces(),               newInvocationHandler(){               publicObject invoke(Object proxy, Method method, Object[] args)                           throwsThrowable{                     }

目标类中的方法怎么在代理类中执行的呢?

实际上目标类中的方法每被调用一次,就会执行一次invote方法。

InvocationHander的运行原理是:

Invodler.invote(object proxy,Method method,Object[] args);

 Objproxy.add(“fdsmfkdsl”);

proxy 接受Objproxy, method接受 add(), args 接受"fdsmfkdsl";

下面是一个代理类的代码:

//代理类publicclassProxyTest {    publicstaticvoid main(String[] args) throws Exception {        ArrayList al=newArrayList();    Collectionconllection = (Collection)getProxy(al,newMyAdvice());        conllection.add("aaaa");        conllection.add("bbbb");        conllection.add("cccc");        conllection.add("dddd");        System.out.println(conllection);    }    privatestatic Object getProxy(final Objectobj,final Advice ad)    {        Collectionconllection=(Collection)Proxy.newProxyInstance(             obj.getClass().getClassLoader(),            obj.getClass().getInterfaces(),            newInvocationHandler(){                ArrayListal=newArrayList();                public Objectinvoke(Object proxy, Method method, Object[] args)                        throwsThrowable {                    ad.beforeMethod(method);                Object val=method.invoke(al, args);                ad.afterMethod(method);                    returnval;                }            });        returnconllection;    }      } importjava.lang.reflect.Method;publicclassMyAdviceimplementsAdvice {longstart;    @Override    publicvoidafterMethod(Method method) {        // TODO Auto-generated method stub        longstart=System.currentTimeMillis();    }    @Override    publicvoidbeforeMethod(Method method) {        // TODO Auto-generated method stub        longend=System.currentTimeMillis();               System.out.println(method.getName()+"yunxing de shijan"+(end-start));    }} 

importjava.lang.reflect.Method;publicinterface Advice {voidbeforeMethod(Method method);voidafterMethod(Method method);}
利用动态代理模拟Spring框架

代码如下:

importjava.io.IOException;importjava.io.InputStream;importjava.util.Properties;importcn.itcast.day3.Advice;publicclass BeanFactory {    Properties props = new Properties();    publicBeanFactory(InputStreamips){        try {            props.load(ips);        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    public Object getBean(String name){        String className =props.getProperty(name);        Object bean = null;        try {            Class clazz =Class.forName(className);            bean = clazz.newInstance();        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        if(bean instanceofProxyFactoryBean){            Object proxy = null;            ProxyFactoryBeanproxyFactoryBean =(ProxyFactoryBean)bean;            try {                Advice advice =(Advice)Class.forName(props.getProperty(name +".advice")).newInstance();                Object target =Class.forName(props.getProperty(name + ".target")).newInstance();                proxyFactoryBean.setAdvice(advice);                proxyFactoryBean.setTarget(target);                proxy =proxyFactoryBean.getProxy();            } catch (Exception e) {                // TODO Auto-generated catchblock                e.printStackTrace();            }            return proxy;        }        return bean;    }}

importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;importcn.itcast.day3.Advice;publicclass ProxyFactoryBean {     private Advice advice;    private Object target;       public Advice getAdvice() {        return advice;    }    public void setAdvice(Advice advice) {        this.advice = advice;    }    public Object getTarget() {        return target;    }    public void setTarget(Object target) {        this.target = target;    }    public Object getProxy() {        Object proxy3 = Proxy.newProxyInstance(                target.getClass().getClassLoader(),                target.getClass().getInterfaces(),                newInvocationHandler(){                    public Object invoke(Objectproxy, Method method, Object[] args)                            throwsThrowable {                        advice.beforeMethod(method);                        Object retVal =method.invoke(target, args);                        advice.afterMethod(method);                        returnretVal;                                          }                }                );        return proxy3;    } }

importjava.io.InputStream;importjava.util.Collection;publicclass AopFrameworkTest {    /**     * @paramargs     */    public static void main(String[] args)throws Exception {        // TODO Auto-generated method stub        InputStreamips =AopFrameworkTest.class.getResourceAsStream("config.properties");        Object bean = newBeanFactory(ips).getBean("xxx");        System.out.println(bean.getClass().getName());        ((Collection)bean).clear();    }}

总结:代理:就是给目标类添加一个壳子,可以有效地添加系统功能和控制是否调用目标类。

         静态代理:就是把代理的目标类已经人工的添加进去,当代码编译时,就会生成相应的class文件。

静态代理类优缺点 
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。 
缺点: 
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。 
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。 

         动态代理:就是有特定的方法,自动生成传入的目标类的代理类,在编译时,不会出现相应的class类。在程序运行时,运用反射机制动态创建而成

动态代理的优点和美中不足 
优点: 
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。在本示例中看不出来,因为invoke方法体内嵌入了具体的外围业务(记录任务处理前后时间并计算时间差),实际中可以类似Spring AOP那样配置外围业务。 
美中不足: 

Proxy 已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持 interface 代理的桎梏,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫 Proxy。Java 的继承机制注定了这些动态代理类们无法实现对 class 的动态代理,原因是多继承在 Java 中本质上就行不通。 


------- 物联云培训java培训、期待与您交流! ----------  

0 0
原创粉丝点击