代理模式
代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。动态代理是SpringAop的底层。
代理模式的分类
- 静态代理
由程序员创建代理类或特定工具自动生成源代码再对其编译,在程序运行前代理类的 .class 文件就已经存在了。
- 动态代理
在程序运行时,运用反射机制动态创建而成。
代理模式的优点:
- 可以使真实角色的操作更加纯粹!不用关注一些公共的业务。
- 公共业务交给代理角色,实现了业务的分工
- 公共业务扩展的时候,方便集中管理。
静态代理
- 定义一个接口;
- 被代理类实现接口;
- 代理类引用被代理类,并且通过被代理类的方法实现接口。
public interface rental { void doRental(); }
public class landlord implements rental{ @Override public void doRental() { System.out.println("房东要出租房子"); } }
public class intermediary implements rental{
private landlord landlord;
public intermediary(landlord landlord) { this.landlord = landlord; } @Override public void doRental() { landlord.doRental(); seeHouse(); writeContract(); }
public void seeHouse() { System.out.println("中介带你看房子"); }
public void writeContract() { System.out.println("中介和你签合同"); } }
public class Tenants { public static void main(String[] args) { landlord landlord = new landlord(); intermediary intermediary = new intermediary(landlord); intermediary.doRental(); } }
|
静态代理的缺点:
一个真实角色就会产生一个代理角色,代码量翻倍,开发效率变低。
动态代理
- 接口还是上面的rental接口;
- 代理类landlord实现接口与静态代理相同;
- 动态代理没有代理类,而是通过java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy来实现
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) { this.target = target; } public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { java.lang.Object result = method.invoke(target, args); seeHouse(); writeContract(); return result; } }
|
这段代码适用于任何接口的动态代理,即拿即用。
我们在上面类中可以随意添加我们需要的方法,此处我将其修改如下:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) { this.target = target; } public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { java.lang.Object result = method.invoke(target, args); seeHouse(); writeContract(); return result; }
public void seeHouse() { System.out.println("中介带你看房子"); }
public void writeContract() { System.out.println("中介和你签合同"); } }
|
具体使用
public class Tenants { public static void main(String[] args) { landlord landlord = new landlord(); ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(); proxyInvocationHandler.setTarget(landlord); rental rental = (rental) proxyInvocationHandler.getProxy(); rental.doRental(); } }
|