黑马程序员_ java高新之动态代理

来源:互联网 发布:淘宝店招代码生成器 编辑:程序博客网 时间:2024/05/17 16:44
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

1、代理的概念

代理类就是将目标类实现的接口和参数传入从而可以在代理类中对被代理的对象进行操作

2、通过字节码对代理类的使用

1)创建动态类及查看其方法列表信息
<span style="white-space:pre"></span>//获取Collect接口代理的字节码Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);System.out.println(clazzProxy.getName());//获得代理类的构造器Constructor[] constructors = clazzProxy.getConstructors();for(Constructor constructor:constructors){String name = constructor.getName();StringBuilder stringBuilder = new StringBuilder(name);stringBuilder.append('(');Class[] clazzParameterTypes = constructor.getParameterTypes();for(Class clazzType:clazzParameterTypes){stringBuilder.append(clazzType.getName()+",");}if(stringBuilder !=null&& stringBuilder.length()>0)stringBuilder.deleteCharAt(stringBuilder.length()-1);stringBuilder.append(')');System.out.println(stringBuilder);}//获取代理类的方法System.out.println("Method方法开始");Method[] methods = clazzProxy.getMethods();for(Method method:methods){String name = method.getName();StringBuilder stringBuilder = new StringBuilder(name);stringBuilder.append('(');Class[] clazzParameterTypes = method.getParameterTypes();for(Class clazzType:clazzParameterTypes){stringBuilder.append(clazzType.getName()+",");}if(stringBuilder !=null&& stringBuilder.length()>0)stringBuilder.deleteCharAt(stringBuilder.length()-1);stringBuilder.append(')');System.out.println(stringBuilder);}

输出结果:
$Proxy0
$Proxy0(java.lang.reflect.InvocationHandler)
Method方法开始
add(java.lang.Object)
hashCode)
clear)
equals(java.lang.Object)
toString)
contains(java.lang.Object)
isEmpty)
addAll(java.util.Collection)
iterator)
size)
toArray([Ljava.lang.Object;)
toArray)
remove(java.lang.Object)
containsAll(java.util.Collection)
removeAll(java.util.Collection)
retainAll(java.util.Collection)
isProxyClass(java.lang.Class)
getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;)
newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)
getInvocationHandler(java.lang.Object)
wait)
wait(long,int)
wait(long)
getClass)
notify)
notifyAll)
    
2)创建动态类的实例对象及调用其方法
步骤:
a、创建动态类的实例对象。通过反射获得构造方法。 
b、编写一个最简单的InvocationHandler类。 
c、调用构造方法创建动态类的实例对象,并将编写的InvocationHandler类的实例对象传进去。 
d、将创建动态类的实例对象的代理改成匿名内部类的形式编写。
代码如下:
<span style="white-space:pre"></span>//代理就是把想要代理的类的接口交给代理类,但在代理类内部的InvocationHandler接口的方法还是要传入代理的目标对象,到底<span style="white-space:pre"></span>//<span style="white-space:pre"></span>还是对目标对象的操作Collection collection2 = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{Collection.class},new InvocationHandler() {ArrayList  target = new ArrayList();@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//把代理对象collect2获得的参数args和操作方法给目标对象target,让目标对象target对操作<span style="white-space:pre"></span>//方法和参数args进行操作;//此步才是代理真正做的事,还是交给被代理的对象做事Object retVal =  method.invoke(target, args);System.out.println(method.getName()+"方法正在运行");return retVal;}});collection2.add("dsf");collection2.add("dsdfsf");collection2.add("dsdsf");System.out.println(collection2.size());//Object类只将hashCode ,equals ,toString方法交给InvocationHandler处理System.out.println(collection2.getClass().getName());
输出结果:
add方法正在运行
add方法正在运行
add方法正在运行
size方法正在运行
3
$Proxy0


小结:代理就是把想要代理的类的接口交给代理类,但在代理类内部的InvocationHandler接口的方法还是要传入代理的目标对象,到底还是对目标对象的操作。

3、动态代理

1)aop:交叉业务的编程问题即为面向切面的编程(Aspect oriented program ,简称AOP),AOP的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的。使用代理技术正好可以解决这种问题,所以代理是实现AOP功能的核心和关键技术。

2)动态代理技术

JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。JVM生成的动态类必须实现一个或 多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。 

CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现 接口的类生成动态代理类,那么可以 使用CGLIB库。 

代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四 个位置加上系统功能代码:

a、在调用目标方法之前 

b、在调用目标方法之后 

c、在调用目标方法前后 

d、在处理目标方法异常的catch块中




0 0
原创粉丝点击