代理模式和 Java 动态代理
本文涉及到代理模式和 Java 反射的相关知识,如果对这两部分不熟的话,可以阅读作者的 代理模式 和 Java 反射教程。
代理模式
在代理模式中涉及到一个接口以及这个接口的两个实现类。这两个实现类,其中一个类为代理类,另一个为被代理的类。
一个接口
MyInterface.java
public interface MyInterface {
void doSomething1();
void doSomething2();
void doSomething3();
}
被代理的类
MyTest.java
public class MyTest implements MyInterface {
@Override
public void doSomething1() {
System.out.println("doSomething1() called");
}
@Override
public void doSomething2() {
System.out.println("doSomething2() called");
}
@Override
public void doSomething3() {
System.out.println("doSomething3() called");
}
}
代理类
ProxyTest.java
public class ProxyTest implements MyInterface {
// 被代理对象
private MyInterface realMyInterface;
public ProxyTest(MyInterface realMyInterface) {
this.realMyInterface = realMyInterface;
}
@Override
public void doSomething1() {
System.out.println("before doSomething1()");
realMyInterface.doSomething1();
System.out.println("after doSomething1()");
System.out.println();
}
@Override
public void doSomething2() {
System.out.println("before doSomething2()");
realMyInterface.doSomething2();
System.out.println("after doSomething2()");
System.out.println();
}
@Override
public void doSomething3() {
System.out.println("before doSomething3()");
realMyInterface.doSomething3();
System.out.println("after doSomething3()");
System.out.println();
}
}
Demo.java
public class Demo {
public static void main(String[] args) {
MyInterface myInterface = new MyTest();
MyInterface proxy = new ProxyTest(myInterface);
proxy.doSomething1();
proxy.doSomething2();
proxy.doSomething3();
}
}
输出结果:
before doSomething1()
doSomething1() called
after doSomething1()
before doSomething2()
doSomething2() called
after doSomething2()
before doSomething3()
doSomething3() called
after doSomething3()
动态代理
在代理模式中的接口中如果有很多个方法,代理类就需要实现接口中的所有的方法,有些繁琐。有时候我们仅会在被代理方法的前面或后面加上相同或相似的处理,但我们在代理类中仍然需要实现接口中的每一个方法。
代理模式能实现的功能,动态代理也能实现,动态代理实现起来可能还要更简洁。
在代理模式中涉及到一个接口和该接口的两个实现类。在动态代理中涉及到一个接口和该接口的一个实现类和一个实现了 InvocationHandler 的实现类。
一个接口。
MyInterface.java
public interface MyInterface {
void doSomething1();
void doSomething2();
void doSomething3();
}
被代理的类
MyTest.java
public class MyTest implements MyInterface {
@Override
public void doSomething1() {
System.out.println("doSomething1() called");
}
@Override
public void doSomething2() {
System.out.println("doSomething2() called");
}
@Override
public void doSomething3() {
System.out.println("doSomething3() called");
}
}
InvocationHandler.java
public interface InvocationHandler {
// proxy 是代理对象
public Object invoke(Object proxy, Method method, Object[] args);
}
MyInvocationHandler.java
public class MyInvocationHandler implements InvocationHandler {
// 被代理的对象
private MyInterface myInterface;
public MyInvocationHandler(MyInterface myInterface) {
this.myInterface = myInterface;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
// proxy 是代理对象,不过在 invoke 方法中好像一般不会用到它
System.out.println("before " + method.getName() + "()");
// 通过反射调用被代理对象的 method
Object returnValue = method.invoke(myInterface, args);
System.out.println("after " + method.getName() + "()");
System.out.println();
return returnValue;
}
}
Demo.java
public class Demo {
public static void main(String[] args) {
// 被代理的对象
MyInterface myInterface = new MyTest();
InvocationHandler invocationHandler = new MyInvocationHandler(myInterface);
// 代理对象
MyInterface myProxy = (MyInterface) Proxy.newProxyInstance(Demo.class.getClassLoader(), new Class[] {MyInterface.class}, invocationHandler);
myProxy.doSomething1();
myProxy.doSomething2();
myProxy.doSomething3();
}
}
输出结果:
before doSomething1()
doSomething1() called
after doSomething1()
before doSomething2()
doSomething2() called
after doSomething2()
before doSomething3()
doSomething3() called
after doSomething3()
代理模式和 Java 动态代理的比较
从输出结果来看,代理模式的输出结果和动态代理的输出结果是完全一样的。
代理模式和动态代理的相同点:
- 两者可以实现同样的功能换句话说用代理模式能实现的用动态代理也能实现。
- 两者都需要一个一个接口和该接口的一个实现类,在本例中是 MyInterface 接口和 MyTest(被代理的类)。
代理模式和动态代理的不同点:
- 代理模式需要自己创建一个代理类,这个代理类和被代理类需要实现同一个接口。而动态代理不需要自己创建代理类,代理类是由 JVM 动态(在运行时)创建的,所以叫动态代理。
- 动态代理中用户需要自己创建一个实现了 InvocationHandler 接口的类。一般来说,这个 invocation handler 有一个成员变量,这个成员变量是被代理的对象,有一个只有一个参数的共有构造方法,用于在创建 invocation handler 的时候把被代理的对象传入构造方法。
- 代理模式中用户需要在代理类中去实现接口中的每一个方法,在动态代理中所有的逻辑处理都放在 invocation handler 中的 invoke() 方法中,由 invoke() 方法统一处理。
- 动态代理中代理类关联了一个 InvocationHandler 对象,调用代理对象的某个方法时代理对象会把这个调用请求转发给 InvocationHandler 对象由 InvocationHandler 的 invoke() 方法来统一处理。
还没有评论,来说两句吧...