黑马程序员__动态代理

来源:互联网 发布:windows系统优化软件 编辑:程序博客网 时间:2024/06/05 16:18

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

今天重新看了一下动态代理和反射的视频。基本上搞懂了稍微测试和总结下。

动态代理:

1、JVM可以在运行期间动态的生成出类的字节码,这种动态生成的类往往被用作代理类,也就是动态代理。

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

3、代理类Proxy的构造方法有参数,并且为InvocationHandler类型,所以在用反射返回Class类型的对象时,不能调用newInstance()为其创建一个实例。

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

 

二、用反射操作的基本步骤:

       1、得到类的字节码。可以通过 对象.getClass(),类.class,Class.forName("类名")返回一个Class类型的对象。

       2、Class类里面有各种各样的方法,得到类的各种成分,getMethod(),getConstructor()等等。但是注意:如果类里面的各种成分声明为private的话,要注意调用的方法有所不同。

       3、得到各种成分之后就可以操作这样成分,但是操作类里面的“方法”这个成分就不一样,就要得到类的实例对象(静态方法除外),得到实例对象也有两种:

       1)通过Class类的newInstance()但是如果类的构造方法有参数的话就不可以用。这个只能得到无参的构造方法的实例对象。

       2)通过getConstructor(类型.class)来得到构造方法,返回的是Constructor类型的对象,然后用Constructor类型的对象去调用newInstance(参数)。

三、Proxy类:

Proxy类里面有一个方法:

newProxyInstance(ClassLoader loader, Class<?>[]interfaces, InvocationHandler h);

可以直接创建一个实例对象。下面是一些测试代码:用于通过Proxy类动态的创建代理类。

package net.proxy;

 

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.util.*;

 

public class ProxyTest {

       publicstatic void main(String[] args) throws Exception,

                     NoSuchMethodException{

              Classclazz = Proxy.getProxyClass(Collection.class.getClassLoader(),

                            Collection.class);

              //clazz.newInstance();这个是不可以的。因为产生的动态类的构造方法是有参数的。

              Constructorconstructor = clazz.getConstructor(InvocationHandler.class);

              CollectioncollProxy = (Collection) constructor

                            .newInstance(newInvocationHandler() {

                                   @Override

                                   publicObject invoke(Object proxy, Method method,

                                                 Object[]args) throws Throwable {

                                          returnnull;

                                   }

 

                            });

              //这个方法实际上是上面的两个步骤(得到Class类型的对象也就是代理类的字节码和创建实例)都给做了

              CollectioncollProxy1 = (Collection) Proxy.newProxyInstance(

                            Collection.class.getClassLoader(),

                            newClass[] { Collection.class }, new InvocationHandler() {

                                   ArrayListtarget = new ArrayList();

 

                                   @Override

                                   publicObject invoke(Object proxy, Method method,

                                                 Object[]args) throws Throwable {

                                          ObjectretVal = method.invoke(target, args);// 这个是反射中的Method中调用目标对象方法的方法。args是为目标对象方法传递的参数。

                                          returnretVal;

                                   }

 

                            });

              collProxy1.add("xxx");

              //System.out.println(collProxy1);

              //System.out.println(collProxy1.toString());

              //System.out.println(collProxy1.size());

 

              finalArrayList target = new ArrayList();

              CollectioncollProxy2 = (Collection) Proxy.newProxyInstance(target

                            .getClass().getClassLoader(),new Class[] { Collection.class },

                            newInvocationHandler() {

                                   @Override

                                   /**

                                    * @param proxy 为代理对象:collProxy2

                                    * @param method 为代理对象要调用的方法

                                    * @param args 为方法的参数

                                    * 参照下面的collPrxy2.add("xxx");

                                    * */

                                   publicObject invoke(Object proxy, Method method,

                                                 Object[]args) throws Throwable {

                                          ObjectretVal = method.invoke(target, args);// 这个是反射中的Method中调用目标对象方法的方法。args是为目标对象方法传递的参数。

                                          returnretVal;

                                   }

 

                            });

              //代理的内部实现:调用add 方法,则去找invocationHandler

              //里面的invoke方法-->调用method的invoke方法。这样返回值从handler中的invoke取。

              //如果retVal为空的话,就不可以用collProxy2.size()因为他返回的是int

              //,当它去handler去取的时候就返回空。。空==int ???所以出错了。

              collProxy2.add("xxx");

              //System.out.println(collProxy1);

              System.out.println(collProxy2.toString());

              System.out.println(collProxy2.size());

       }

}

 

 


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

原创粉丝点击