黑马程序员 代理学习

来源:互联网 发布:淘宝原单男装店铺 编辑:程序博客网 时间:2024/05/17 07:29

               ----------- android培训java培训、期待与您交流! ------------

代理

生活中,消费者与厂商之间有代理商。代理商提供了一定的功能,如:将货物送到消费者手中,保鲜等

程序中,也有类似的中间件-代理类。

代理类:与目标类有相同的接口(方法集合),代理中的每个方法都调用目标类的方法,提供了一些附加的功能,如计算方法的运行时间,异常处理、事务管理、日志等。

具体应用:如果采用工厂模式和配置文件的方式进行管理,在配置文件中配置是使用目标类,还是代理类,很方便的进行切换。同时以后若想去掉附加的功能,也很方便。

 

示例代码 

class A {//目标类void method() {}}class XProxy {//代理类void method() {//和目标类有相同的方法startTime;//增加系统功能A.method();//调用目标类的方法endTime;//增加系统功能}}


代理架构图:

 

 

 

AOP

代理是实现AOP功能的核心和关键技术。

那什么是AOP?

答:Aspect oriented program,面向方面编程。

 

什么是交叉业务?

答:安全、事务、日志等功能要贯穿到很多个模块中,它们就是交叉业务。

 

AOP的目标:使交叉业务模块化。

如何实现的?

答:采用将切面代码移动到原始方法的周围。这与直接在方法中编写切面面代码是一样的。(这里的切面代码:就是附加的功能代码)

实际开发中,将切面代码封装成对象,传递给InvocationHandler的invoke()方法。

 

 

 

动态代理技术

要为系统中的各种接口的类增加代理功能,若全部采用静态代理的方式,将需要很多的代理类。

 

动态代理类:JVM可以在运行时期动态的生成类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。

JVM生成的动态类必须实现一个或多个接口,所以其只能代理于具有相同接口的目标类。

 

CGLIB库:可以动态生成一个类的子类,一个类的子类也可作为此类的代理,所以要为一个没有实现接口的类生成代理,可以用CGLIB库。(是一个插件)

 

系统功能代码(切面代码)存放于代理方法中的位置:1、调用的目标方法前;2、调用的目标方法后;3、代理方法的异常处理的catch块中。

 

JVM动态生成类的字节码:实例代码

动态生成一个实现了Collection接口的类字节码,并使用反射技术查看这个动态类的一些内部信息。

import java.util.*;import java.lang.reflect.*;class ProxyDemo {public static void main(String[] args) {Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);    //动态生成一个类System.out.println(clazzProxy.getName());System.out.println("----------构造方法:-------");Constructor[] constructors = clazzProxy.getConstructors();for(Constructor constructor : constructors) {System.out.println("构造方法:" + constructor);}System.out.println("----------普通方法:-------");Method[] methods = clazzProxy.getMethods();for(Method method : methods) {System.out.println("普通方法:" + method);Class[] clazzParams = method.getParameterTypes();for(Class clazzParam : clazzParams) {System.out.println("----参数为:" + clazzParam.getName());}Type[] types = method.getGenericExceptionTypes();for(Type type : types) {System.out.println("--------方法抛出的异常类型为:" + type);}}}}


创建动态代理类的实例对象,如下

Collection proxy3 = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(),//第一个参数:用于产生动态类的接口的类加载器 new Class[]{Collection.class},//第二个参数:用于产生动态类的接口的类型数组 new InvocationHandler(){//第三个参数:实现了Invocation接口的匿名类对象ArrayList target = new ArrayList();//目标类对象public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{  //动态代理类的方法调用函数long startTime = System.currentTimeMillis();Object retVal = method.invoke(target, args);//目标类方法调用函数long endTime = System.currentTimeMillis();System.out.println(method.getName() + "方法运行时间" + (endTime - startTime));return retVal;}});proxy3.add("Hello");proxy3.add("Java");System.out.println("集合元素个数:" + proxy3.size());}


InvocationHandler对象运行原理:

Client程序调用proxyObj.add("AB")方法时,涉及三要素:1、哪个对象调用的,proxyObj    2、调用的是哪个方法    3、调用方法的参数

调用的过程:调用用proxyMethod.invoke(),这个方法需要目标方法的返回值,它会自动去调用targetMethod.invoke(),然后将返回值传递给proxyMethod.invoke(),再传递给调用者;传值的过程中,代理类的附加代码也相继运行。

 

分析代理类的方法:

class Proxy$ {add(Object obj) {return handler.invoke(Object proxy, Method method, Object[] args)}int size() {return handler.invoke(this, this.getClass().getMethod("size"), null);}}

 

动态代理工作原理图: 

 

                                ----------------------- android培训java培训、期待与您交流! ----------------------

                                详情请查看:http://edu.csdn.net/heima

 

原创粉丝点击