黑马程序员_JAVA学习笔记10

来源:互联网 发布:win7网络和共享打不开 编辑:程序博客网 时间:2024/06/06 19:03

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net

代理模式:

JAVA动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:

1.Interface InvocationHandle该接口中仅定义了一个方法:public object invoke(Object obj,Method method,Object[] args)

在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。

2.Proxy:该类即为动态代理类,作用类似于上例中的proxySubject


下面是利用代理动态生成类对象。上面构造方法中要接收一个带invocationHander的参数,所以紧跟着要实现这个接口。然后才可newInstance。上面调用 size方法时会发生错误, 原因可以在下面一段代码中找, 因为 我调用 size方法,但size方法的返回值为int ,但Invoke返回的确是 Null所以就会发生错误。

Class clazzprox = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);

Constructor[] constructors = clazzprox.getConstructors();

for(Constructor c : constructors)

{

String name = c.getName();

StringBuilder s = new StringBuilder(name);

s.append("(");

Class[] p = c.getParameterTypes();

for(Class cla : p)

{

s.append(cla.getName()).append(",");

}

s.append(")");

System.out.println(s);

}

}

Constructor constructor = clazzProxy1.getConstructor

class MyInvocationHander1 implements InvocationHandle{

public Object invoke(Object proxy, Method method) throws Throwable{

return null;

}

}

collection proxy1 = (Collection)constructor.newInstance();

System.out.println(proxy1);

proxy1.clear();

让JVM创建动态类及其实例对象,需要给它提供的信息如下:

1.生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知;

2.产生的类字节码必须有个一个关联的类加载器对象;

3.生成的类中的方法的代码是怎样的,也得由我们提供。把我们的代码写在一个约定好了接口对象的方法中,把对象传给它,它调用我的方法,即相当于插入我的代码。提供执行代码的对象就是那个InvocationHandler对象,它是在创建动态类的实例对象的构造方法时传递进去的。在上面的InvocationHandler对象的invoke方法中加一点代码,就可以看到这些代码被调用运行了。

用Proxy.newInstance方法直接一步就创建出代理对象。

最后 可以 用Proxy.newInstance 方法直接创建对象,不用向上面那样麻烦了。

//Proxy.newProxyInstance()方法,直接动态创建类

Collection c3 = (Collection)Proxy.newProxyInstance(

Collection.class.getClassLoader(),

new Class[]{Collection.class},

new InvocationHandler(){

//放在这里面 就不是 每次创建 一个arrayList对象了。

//ArrayList al = new ArrayList();

@Override

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

throws Throwable {

ArrayList al = new ArrayList();

long beginTime = System.currentTimeMillis();

Object o = method.invoke(al, args);

long endTime = System.currentTimeMillis();

System.out.println(method.getName() + " time: "

(endTime - beginTime));

return o;

}

});

c3.add("aaa");

c3.add("bbb");

c3.add("ccc");

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

输出结果:

add time: 0

add time: 0

add time: 0

size time: 0

0

这是上面代码的输出结果,为什么会输出 ? 因为每add 或 调用size 方法时,就会去调用invoke方法,而arrayList是在invoke方法里面new 出来的,所以每次都是不同的对象,所以 size0, 如果把new arrayList 方法类里面结果就会输出 

Proxy objectg 身上继承的方法 , 只有 hashCode,equals,toString 会给InvocationHanderl 自己,所以上面打印对象时,由于返回值是null 所以才会打印null。其他的方法 都有实现 。


总结动态代理的步骤:

1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法。

2.创建被代理的类以及接口。

3.通过Proxy的静态方法newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler);创建一个代理。

4.通过代理调用方法。




0 0
原创粉丝点击