Proxy是一种结构设计模型,主要解决对象直接访问带来的问题,代理又分为静态代理和动态代理(JDK代理、CGLIB代理。
静态代理:又程序创建的代理类,或者特定的工具类,在平时开发中经常用到这种代理模式,这种一般在程序运行前就已经生成对应的class文件;
动态代理:在程序运行时通过反射机制动态创建。
下面通过一个场景实现以下三种代理方式
几种代理方式都会用到Subject、RealSubject,现在这里定义
Store.java(Subject):定义两个接口operate(运营),business(交易)。
public interface Store { /** * 店铺运营 */ public void operate(); /** * 店铺交易 */ public void business(); }
PersonStore.java(RealSubject) 单个用户运营
public class PersonStore implements Store { @Override public void operate() { System.out.println("个人商店运营"); } @Override public void business() { System.out.println("个人商店交易"); } }
静态代理的实现比较简单,代理类通过实现与目标对象相同的接口,并在类中维护一个代理对象,这种场景用于个体商家比较少的情况,如果多的话代理类十分繁多、不易维护
ProxyStroe.java(proxy):在代理平台运营是收取管理费用100,这个代理类需要实现Store接口,并制定目标类target(PersonStore)。
public class ProxyStroe implements Store{ private Store personStore = new PersonStore(); @Override public void operate() { System.out.println("收取管理费用100元"); personStore.operate(); } @Override public void business() { personStore.business(); } }
StaticConsumer.java(client):通过创建ProxyStroe去代理PersonStore,并进行操作。
public class StaticConsumer { public static void main(String[] args) { ProxyStroe store = new ProxyStroe(); store.operate(); store.business(); } }
动态代理类是通过接口实现的,利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,
在调用具体方法前调用InvokeHandler来处理。
JDKStoreHandler.java(proxy):通过实现InvocationHandler接口的invoke方法,在里面进行反射调用,newProxyInstanse通过目标对象创建真是对象。
public class JDKStoreHandler implements InvocationHandler { /** * 目标对象 */ private Object targetObject; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if("operate".equals(method.getName())){ System.out.println("收取管理费用100元"); } return method.invoke(targetObject, args); } /** * * @param targetObject * @return */ public Object newProxyInstanse(Object targetObject){ this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this); } }
JDKDynamicConsumer.java(proxy):通过JDKStoreHandler的newProxyInstanse创建真实目标对象,并调用接口的方法
public class JDKDynamicConsumer { public static void main(String[] args) { Store store = (Store)new JDKStoreHandler().newProxyInstanse(new PersonStore()); store.operate(); store.business(); } }
cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
CglibProxy.java(proxy):需要实现MethodInterceptor的intercept方法,并进行反射调用。通过createProxyObject创建真实对象,这里是根据目标对象直接生成对象。
public class CglibProxy implements MethodInterceptor{ /** * CGlib需要代理的目标对象 */ private Object targetObject; public Object createProxyObject(Object targetObject){ this.targetObject = targetObject; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(targetObject.getClass()); enhancer.setCallback(this); Object proxyObj = enhancer.create(); return proxyObj; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { if("operate".equals(method.getName())){ System.out.println("收取管理费用100元"); } return method.invoke(targetObject, objects); } }
CglibDynamicConsumer.java(client):通过CglibProxy的createProxyObject创建真实目标对象,对进行方法调用
public class CglibDynamicConsumer { public static void main(String[] args) { Store store = (Store)new CglibProxy().createProxyObject(new PersonStore()); store.operate(); store.business(); } }
源码已上传: https://github.com/itrickzhan...