代理模式主要有两种静态代理和动态代理
静态代理
比如要在输出HelloWorld前打印一个字符串Welcome
A:先定义一个接口类
Java代码
package ttitflyproxy;
public interface HelloWorld {
public void print();
// public void say();
}
package ttitflyproxy;
public interface HelloWorld {
public void print();
// public void say();
}
B: 定义一个该接口的实现类
Java代码
package ttitflyproxy;
public class HelloWorldImpl implements HelloWorld{
public void print(){
Systemoutprintln(HelloWorld);
}
// public void say(){
// Systemoutprintln(Say Hello!);
// }
}
package ttitflyproxy;
public class HelloWorldImpl implements HelloWorld{
public void print(){
Systemoutprintln(HelloWorld);
}
// public void say(){
// Systemoutprintln(Say Hello!);
// }
}
C:定义一个静态代理类
Java代码
package ttitflyproxy;
public class StaticProxy implements HelloWorld{
public HelloWorld helloWorld ;
public StaticProxy(HelloWorld helloWorld){
thishelloWorld = helloWorld;
}
public void print(){
Systemoutprintln(Welcome);
//相当于回调
helloWorldprint();
}
// public void say(){
// //相当于回调
// helloWorldsay();
// }
}
package ttitflyproxy;
public class StaticProxy implements HelloWorld{
public HelloWorld helloWorld ;
public StaticProxy(HelloWorld helloWorld){
thishelloWorld = helloWorld;
}
public void print(){
Systemoutprintln(Welcome);
//相当于回调
helloWorldprint();
}
// public void say(){
// //相当于回调
// helloWorldsay();
// }
}
D: 一个测试类:
Java代码
package ttitflyproxy;
public class TestStaticProxy {
public static void main(String[] args){
HelloWorld helloWorld = new HelloWorldImpl();
StaticProxy staticProxy = new StaticProxy(helloWorld);
staticProxyprint();
// staticProxysay();
}
}
package ttitflyproxy;
public class TestStaticProxy {
public static void main(String[] args){
HelloWorld helloWorld = new HelloWorldImpl();
StaticProxy staticProxy = new StaticProxy(helloWorld);
staticProxyprint();
// staticProxysay();
}
}
可以看出静态代理类有一个很不爽的缺点当如果接口加一个方法(把上面所有的代码的注释给去掉)所有的实现类和代理类里都需要做个实现这就增加了代码的复杂度动态代理就可以避免这个缺点
动态代理
动态代理与普通的代理相比较最大的好处是接口中声明的所有方法都被转移到一个集中的方法中处理(invoke)这样在接口方法数量比较多的时候我们可以进行灵活处理而不需要像静态代理那样每一个方法进行中转
动态代理类只能代理接口代理类都需要实现InvocationHandler类实现invoke方法该invoke方法就是调用被代理接口的所有方法时需要调用的该invoke方法返回的值是被代理接口的一个实现类
代理类
Java代码
package ttitflyproxy;
import javalangreflectInvocationHandler;
import javalangreflectMethod;
import javalangreflectProxy;
//动态代理类只能代理接口代理类都需要实现InvocationHandler类实现invoke方法该invoke方法就是调用被代理接口的所有方法时需要调用的该invoke方法返回的值是被代理接口的一个实现类
public class DynamicProxy implements InvocationHandler{
private Object object;
//绑定关系也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时执行invoke方法
//ProxynewProxyInstance的第三个参数是表明这些被拦截的方法执行时需要执行哪个InvocationHandler的invoke方法
public Object bindRelation(Object object){
thisobject = object;
return ProxynewProxyInstance(objectgetClass()getClassLoader() objectgetClass()getInterfaces()this);
}
//拦截关联的这个实现类的方法被调用时将被执行
public Object invoke(Object proxy Method method Object[] args) throws Throwable {
Systemoutprintln(Welcome);
Object result = methodinvoke(object args);
return result;
}
}
package ttitflyproxy;
import javalangreflectInvocationHandler;
import javalangreflectMethod;
import javalangreflectProxy;
//动态代理类只能代理接口代理类都需要实现InvocationHandler接口覆盖invoke方法该invoke方法就是调用被代理接口的所有方法时需要调用的该invoke方法返回的值是被代理接口的一个实现类
public class DynamicProxy implements InvocationHandler{
private Object object;
//绑定关系也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时执行invoke方法
//ProxynewProxyInstance的第三个参数是表明这些被拦截的方法执行时需要执行哪个InvocationHandler的invoke方法
public Object bindRelation(Object object){
thisobject = object;
return ProxynewProxyInstance(objectgetClass()getClassLoader() objectgetClass()getInterfaces()this);
}
//拦截关联的这个实现类的方法被调用时将被执行
public Object invoke(Object proxy Method method Object[] args) throws Throwable {
Systemoutprintln(Welcome);
Object result = methodinvoke(object args);
return result;
}
}
测试类
Java代码
package ttitflyproxy;
public class TestDynamicProxy {
public static void main(String[] args){
HelloWorld helloWorld = new HelloWorldImpl();
DynamicProxy dp = new DynamicProxy();
//在这里绑定的是HelloWorld也就是HelloWorld是被代理接口所以绑定关系时需要传递一个HelloWorld的实现类的实例化对象
HelloWorld helloWorld = (HelloWorld)dpbindRelation(helloWorld);
helloWorldprint();
helloWorldsay();
//helloWorld将不被拦截
HelloWorld helloWorld = new HelloWorldImpl();
helloWorldprint();
helloWorldsay();
}
}
package ttitflyproxy;
public class TestDynamicProxy {
public static void main(String[] args){
HelloWorld helloWorld = new HelloWorldImpl();
DynamicProxy dp = new DynamicProxy();
//在这里绑定的是HelloWorld也就是HelloWorld是被代理接口所以绑定关系时需要传递一个HelloWorld的实现类的实例化对象
HelloWorld helloWorld = (HelloWorld)dpbindRelation(helloWorld);
helloWorldprint();
helloWorldsay();
//helloWorld将不被拦截
HelloWorld helloWorld = new HelloWorldImpl();
helloWorldprint();
helloWorldsay();
}
}
在测试类里调用实现类的print和say方法因为代理类里代理了HelloWorld的所有方法所以就不需要像静态代理类那样一一实现了
总结由程序员创建或由特定工具自动生成源代码再对其编译在程序运行前代理类的class文件就已经存在了
动态代理类在程序运行时运用反射机制动态创建而成
代理类可以为委托类预处理消息把消息转发给委托类和事后处理消息等动态代理类的字节码在程序运行时由Java反射机制动态生成无需程序员手工编写它的源代码动态代理类不仅简化了编程工作而且提高了软件系统的可扩展性因为Java 反射机制可以生成任意类型的动态代理类