真实动作的前面和后面分别做一些行为。真实动作使用委托的方式来调用。
静态代理
public interface Subject {
void buyTicket();
}
public class SubjectImpl implements Subject {
@Override
public void buyTicket() {
System.out.println("买票");
}
}
public class SubjectProxy implements Subject {
private Subject subject;
public SubjectProxy(Subject subject) {
this.subject = subject;
}
@Override
public void buyTicket() {
this.doBefore();
subject.buyTicket();
this.doAfter();
}
private void doBefore() {
System.out.println("doBefore");
}
private void doAfter() {
System.out.println("doAfter");
}
}
动态代理
public class DynamicSubjectPorxy implements InvocationHandler {
private Subject subject;
public DynamicSubjectPorxy(Subject subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
this.doBefore();
Object res = method.invoke(subject, args);
this.doAfter();
return res;
}
private void doBefore() {
System.out.println("doBefore");
}
private void doAfter() {
System.out.println("doAfter");
}
}
动态代理的应用会比较多,其实原理挺简单,就是在运行时动态得给某个接口生成一个对象,这个对象实现了目标接口。在JDK中,开发者只需要实现InvocationHandler接口,重写invoke方法。通过 method.invoke(subject, args)方法实现目标方法的调用。那在调用目标方法之前或者调用之后做些什么完全由开发者控制。甚至目标方法都不一定要调用,或者目标方法都不一定有。
如果对于动态代理不熟悉的朋友,务必要亲自动手去写各种案例,否则很难在脑子里形成非常直接的思维。
代理在RPC场景中的应用,比如在Dubbo框架中,服务消费方Consumer只有接口的声明,并没有具体实现,具体实现在服务提供方。那我们就需要给服务消费方的所有接口生成动态代理。当调用服务时,会进入invoke方法。invoke方法中就需要把入参对象等相关信息序列化之后通过TCP方式发送给服务提供方,后续就不在这边细说了。关于Dubbo的服务调用方式相关原理可以参考文档 dubbo服务导出和引入
查看全部 浅谈模式 - 汇总篇