------- android培训、java培训、期待与您交流! ----------
java中的动态代理和静态代理的比较:
静态代理:比如要在输出“HelloWorld”前打印一个字符串“Welcome”
A:先定义一个接口类
package ttitfly.proxy; public interface HelloWorld { public void print(); // public void say(); } |
package ttitfly.proxy;
public class HelloWorldImpl implements HelloWorld{
public void print(){ System.out.println("HelloWorld"); } // public void say(){ // System.out.println("Say Hello!"); // } } |
C:定义一个静态代理类
package ttitfly.proxy;
public class StaticProxy implements HelloWorld{
public HelloWorld helloWorld ; public StaticProxy(HelloWorld helloWorld){ this.helloWorld = helloWorld; }
public void print(){ System.out.println("Welcome"); //相当于回调 helloWorld.print(); }
// public void say(){ // //相当于回调 // helloWorld.say(); // } } |
D: 一个测试类:
package ttitfly.proxy;
public class TestStaticProxy {
public static void main(String[] args){ HelloWorld helloWorld = new HelloWorldImpl(); StaticProxy staticProxy = new StaticProxy(helloWorld); staticProxy.print();
// staticProxy.say(); } } |
可以看出静态代理类有一个很不爽的缺点:当如果接口加一个方法(把上面所有的代码的注释给去掉),
所有的实现类和代理类里都需要做个实现。这就增加了代码的复杂度。动态代理就可以避免这个缺点。
动态代理:
动态代理与普通的代理相比较,最大的好处是接口中声明的所有方法都被转移到一个集中的方法中处理(invoke),
这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
动态代理类只能代理接口,代理类都需要实现InvocationHandler接口,实现invoke方法。该invoke方法就是调用
被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类 。
和动态代理有关的有两个类:
1.interface InvocationHandler
Object invoke( Object proxy , Method method , Object[] args)
2.class Proxy
真正表示动态代理的类,提供两个静态方法:
Class<?>getProxyClass(ClassLoader loader, Class<?>[] interface)
代码演示:
真实的接口:
public interface Hello { //定义一个接口
void sayHello(String to);
void print(String p); } |
public class HelloImpl implements Hello {
public void sayHello(String to) { System.out.println("Say hello to " + to); }
public void print(String s) { System.out.println("print : " + s); }
} |
在这里生成与代理类相关联的InvocationHandler对象 :
public class LogHandler implements InvocationHandler {
private Object dele;
public LogHandler(Object obj) { this.dele = obj; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { doBefore(); //在这里完全可以把下面这句注释掉,而做一些其它的事情 Object result = method.invoke(dele, args); after(); return result; }
private void doBefore() { System.out.println("before...."); }
private void after() { System.out.println("after...."); } } |
最后是测试类:
public class ProxyTest {
public static void main(String[] args) { HelloImpl impl = new HelloImpl(); LogHandler handler = new LogHandler(impl); //这里把handler与impl新生成的代理类相关联 Hello hello = (Hello) Proxy.newProxyInstance(impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler);
//这里无论访问哪个方法,都是会把请求转发到handler.invoke hello.print("All the test"); hello.sayHello("Denny"); }
} |