代理模式
Posted 阿呆很呆非常呆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代理模式相关的知识,希望对你有一定的参考价值。
代理模式,在不改变目标对象的结构、功能的前提下,对目标对象的功能进行增强。
一、静态代理
描述:目标对象和代理对象都实现同一个接口或者同一父类。可以实现在不修改目标对象的基础上,增强目标对象的处理功能。
缺点:固化。可能会存在大量的目标对象和代理对象。并且,如果接口变动的话,那么所有的目标对象和代理对象都必须得修改,不灵活,扩展维护性差。
简单代码演示:
接口类:
package com.cn.agent.staticAgent.byInterface; public interface IUserDao { void save(); }
目标类:
package com.cn.agent.staticAgent.byInterface; /** * 目标对象类 * @author cfang * 2018年5月25日 下午3:50:56 */ public class UserDao implements IUserDao{ public void save(){ System.out.println("--- 调用目标对象方法 ---"); } }
代理类:
package com.cn.agent.staticAgent.byInterface; /** * 静态代理类 * @author cfang * 2018年5月25日 下午3:50:44 */ public class UserDaoProxy implements IUserDao{ //接收并保存目标对象 private IUserDao target; public UserDaoProxy(IUserDao target){ this.target = target; } @Override public void save(){ System.out.println("--- 代理对象类方法调用开始 ---"); target.save(); System.out.println("--- 代理对象类方法调用结束 ---"); } }
测试main方法
package com.cn.agent.staticAgent.byInterface; public class App { public static void main(String[] args) { //目标对象 IUserDao target = new UserDao(); //代理对象 IUserDao proxy = new UserDaoProxy(target); proxy.save(); } }
二、动态代理
描述:目标对象和静态代理相同。代理对象无需实现接口。代理对象的生成,通过jdk的java.lang.reflect.Proxy中的newProxyInstance方法去产生。
简单代码演示:
接口类、目标类代码同静态代理中定义。
代理类
package com.cn.agent.dynamicAgent; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { //存放目标对象类 private Object target; public ProxyFactory(Object target){ this.target = target; } //生成代理对象 public Object getProxyInstance(){ return Proxy.newProxyInstance( target.getClass().getClassLoader(), //ClassLoader -- target.getClass().getInterfaces(), //Class<?>[] interfaces -- new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理类方法执行开始"); Object result = method.invoke(target, args); System.out.println("代理类方法执行结束"); return result; } }); } }
测试main方法
package com.cn.agent.dynamicAgent; public class App { public static void main(String[] args) { //目标对象类 IUserDao target = new UserDao(); System.out.println("原始目标对象类:" + target.getClass()); //代理对象类 IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance(); System.out.println("代理对象类:" + proxy.getClass()); proxy.save(); } }
三、cglib代理
描述:静态代理和动态代理,都要求目标对象去实现一个接口。但是,有时候,目标对象只是个单独的类对象。这时候,可以利用cglib代理,在内存中虚构一个目标对象的子类对象,从而实现对目标对象的功能增强。
简单代码演示
目标类
package com.cn.agent.cglibAgent; public class UserDao { public void save(){ System.out.println("--- 我是目标对象类非final方法 ---"); } public final void save2(){ System.out.println("--- 我是目标对象类final方法 ---"); } public String save3(){ System.out.println("--- 我是有返回的方法 ---"); return "hello world"; } public String save4(String param){ System.out.println("--- 我是带参的有返回的方法 ---"); return param; } }
代理类
package com.cn.agent.cglibAgent; import java.lang.reflect.Method; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.CallbackFilter; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * Enhancer - 主要的增强类 * MethodInterceptor - 方法拦截类,继承自Callback接口 * @author cfang * 2018年5月25日 下午5:26:49 */ public class ProxyFactory implements MethodInterceptor{ //存放目标对象类 private Object target; public ProxyFactory(Object target){ this.target = target; } //创建代理类 public Object getProxyInstance(){ //基本工具类 :设置回调函数、设置父类、生成代理子类 Enhancer enhancer = new Enhancer(); //设置父类 : 设置生成的代理对象的父类 enhancer.setSuperclass(target.getClass()); //设置回调 : Callback接口的实例 enhancer.setCallback(this); //设置多组回调 // Callback[] callbacks = new Callback[]{this,this}; // enhancer.setCallbacks(callbacks); //回调选择器,根据不同返回值,调用callbacks中不同的回调。返回值和callbacks回调的下标对应 // enhancer.setCallbackFilter(new TestFilter()); //生成子类 return enhancer.create(); } /** * 拦截增强方法 */ @Override public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy proxy) throws Throwable { System.out.println("proxy:" + proxy); System.out.println("--- 代理对象增强方法开始 ---"); // Object result = method.invoke(target, arg2); Object result = proxy.invokeSuper(arg0, arg2); System.out.println("--- 代理对象增强方法结束 ---"); return result; } }
测试main方法
package com.cn.agent.cglibAgent; public class App { public static void main(String[] args) { //目标对象 UserDao target = new UserDao(); //代理对象 UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance(); proxy.save(); proxy.save2(); System.out.println(proxy.save3()); System.out.println(proxy.save4("Test")); } }
ps:spring中,基于接口的都是利用jdk动态代理,而其他都是利用cglib的代理机制。
水平有限,欢迎指正。
以上是关于代理模式的主要内容,如果未能解决你的问题,请参考以下文章