Proxy代理模式是什么?
Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
使用场合
如果需要委托类处理某一业务,那么我们就可以先在代理类中统一处理然后在调用具体实现类
代理模式分类
静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
动态代理:在程序运行时运用反射机制动态创建而成。
静态代理
定义接口:
public interface HelloWord {
void print();
}
定义实现类:
public class HelloWordImp1 implements HelloWord {
@Override
public void print() {
System.out.println("hello world");
}
}
定义代理实现类:
public class StaticProxy implements HelloWord {
public HelloWord helloWord;
public StaticProxy (HelloWord helloWord){
this.helloWord = helloWord;
}
@Override
public void print() {
System.out.println("Welcome");
helloWord.print();
}
}
测试类:
public class TeststaticProxy {
public static void main(String[] args) {
HelloWord helloWord = new HelloWordImp1();
StaticProxy staticProxy = new StaticProxy(helloWord);
staticProxy.print();
}
}
优点:
代理使客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合)
缺点:
1)代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
2)代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。
举例说明:
代理可以对实现类进行统一的管理,如在调用具体实现类之前,需要打印日志等信息,这样我们只需要添加一个代理类,在代理类中添加打印日志的功能,然后调用实现类,这样就避免了修改具体实现类。满足我们所说的开闭原则。但是如果想让每个实现类都添加打印日志的功能的话,就需要添加多个代理类,以及代理类中各个方法都需要添加打印日志功能(如上的代理方法中删除,修改,以及查询都需要添加上打印日志的功能)
即静态代理类只能为特定的接口(Service)服务。如想要为多个接口服务则需要建立很多个代理类。代码复用率低,这时候就需要用到动态代理。
动态代理:
定义接口:
public interface Iuser {
void eat(String s);
}
定义实现类:
public class UserImpl implements Iuser{
@Override
public void eat(String s) {
System.out.println("我要吃"+s);
}
}
定义代理类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class InvocationHandlerproxy implements InvocationHandler {
private Object object;
public InvocationHandlerproxy(Object obj){
this.object = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置内容");
method.invoke(object,args);
System.out.println("后置内容");
return null;
}
}
测试类:
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
Iuser iuser = new UserImpl();
InvocationHandlerproxy h = new InvocationHandlerproxy(iuser);
Iuser proxy = (Iuser) Proxy.newProxyInstance(Iuser.class.getClassLoader(),new Class[]{Iuser.class},h);
proxy.eat("苹果");
}
}
为了通过一个代理类完成全部的代理功能,那么我们就需要用动态代理
静态代理,一个代理只能代理一种类型,而且是在编译器就已经确定被代理的对象。而动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象
在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口
和 java.lang.reflect.Proxy 类的支持
动态代理的优点:
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强,动态代理也是一种AOP(面向切面编程)思想的实现。