静态代理和动态代理
(1)什么是代理?
大道理上讲代理是一种软件设计模式,目的是希望能做到代码重用。具体上讲,代理这种设计模式是通过不直接访问被代理对象,却能使用被代理对象的方法,主要是通过代理人作为媒介。这个就好比 商户---->明星经纪人(代理)---->明星这种模式。我们可以不通过直接与明星对话的情况下,而通过明星经纪人(代理)与其产生间接对话。
(2)什么情况下使用代理?
-
设计模式中有一个设计原则是开闭原则,是说对修改关闭对扩展开放,我们在工作中有时会接手很多前人的代码,里面代码逻辑让人摸不着头脑(sometimes the code is really like shit),这时就很难去下手修改代码,那么这时我们就可以通过代理对类进行增强。
即在我们维护一个项目的时候,不知道之前人写的是什么代码,不知道怎么去修改,就可以使用代理模式,在原有模式的基础上,对类进行增强,这样就没有改变原来的代码,但是增强了功能 -
我们在使用RPC框架的时候,框架本身并不能提前知道各个业务方要调用哪些接口的哪些方法 。那么这个时候,就可用通过动态代理的方式来建立一个中间人给客户端使用,也方便框架进行搭建逻辑,某种程度上也是客户端代码和框架松耦合的一种表现。
-
Spring的AOP机制就是采用动态代理的机制来实现切面编程。
(3)静态代理和动态代理
我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理。如果我们在代码编译时就确定了被代理的类是哪一个,那么就可以直接使用静态代理;如果不能确定,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理,比如RPC框架和Spring AOP机制
1、静态代理
- 创建一个接口,接口里面写代理者和被代理者都要使用的方法,即:代理对象和被代理对象都实现同一个接口,并重写了接口中的方法。
- 被代理对象作为代理对象中的一个属性(private Actor actor),(或者直接将接口作为属性,但是创建代理者类时要传入被代理者,然后使用向下转型),代理对象重写接口方法的主要目的是:增强被代理对象的方法。所以在重写接口时,在保证被代理对象重写的方法被调用(this.actor.speak()),同时可以添加任意代码,实现代码增强的逻辑。
Eg:
接口类:
interface Person {
void speak();
}
真实实体类:
class Actor implements Person {
private String content;
public Actor(String content) {
this.content = content;
}
@Override
public void speak() {
System.out.println(this.content);
}
}
代理类:
class Agent implements Person {
private Actor actor;
private String before;
private String after;
public Agent(Actor actor, String bef