Design-代理模式

    技术2023-05-30  47

    代理模式

    介绍静态代理动态代理cglib代理

    介绍

    在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。 介绍 意图:为其他对象提供一种代理以控制对这个对象的访问。 主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。 何时使用:想在访问一个类时做一些控制。 如何解决:增加中间层。 关键代码:实现与被代理类组合。 优点: 1、职责清晰。 2、高扩展性。 3、智能化。 缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。 使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。 注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。

    静态代理

    接口

    public interface Teacher { void teach(); void sya(String name); }

    实现类

    public class EnglishTeacher implements Teacher { @Override public void teach() { System.out.println("上英语课"); } @Override public void sya(String name) { System.out.println("hello:"+name); } }

    代理类

    public class ProxyClass implements Teacher{ private EnglishTeacher englishTeacher; public ProxyClass(EnglishTeacher englishTeacher){ this.englishTeacher = englishTeacher; } @Override public void teach() { englishTeacher.teach(); } @Override public void sya(String name) { englishTeacher.sya(name); } }

    主函数

    public class Client { public static void main(String[] args) { EnglishTeacher englishTeacher = new EnglishTeacher(); ProxyClass proxyClass = new ProxyClass(englishTeacher); proxyClass.teach(); proxyClass.sya("王星宇"); } }

    动态代理

    主函数

    public class Client { public static void main(String[] args) { Teacher target = new EnglishTeacher(); Teacher proxyInstance = (Teacher)new ProxyClass(target).getProxyInstance(); System.out.println(proxyInstance.getClass()); proxyInstance.teach(); proxyInstance.sya("王星宇"); } }

    接口

    public interface Teacher { void teach(); void sya(String name); }

    实现类

    public class EnglishTeacher implements Teacher{ @Override public void teach() { System.out.println("上英语课"); } @Override public void sya(String name) { System.out.println("hello:"+name); } }

    代理

    public class ProxyClass{ private Object target; public ProxyClass(Object target){ this.target = target; } /** public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) //1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定 //2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型 //3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入*/ public Object getProxyInstance(){ return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object invoke = method.invoke(target, args); return invoke; } } ); } }

    cglib代理

    不需要接口

    主函数

    public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //创建目标对象 TeacherDao target = new TeacherDao(); //获取到代理对象,并且将目标对象传递给代理对象 TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance(); //执行代理对象的方法,触发intecept 方法,从而实现 对目标对象的调用 String res = proxyInstance.teach(); System.out.println("res=" + res); } }

    代理类

    import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class ProxyFactory implements MethodInterceptor { private Object target; public ProxyFactory(Object target) { this.target = target; } /** 返回一个代理对象: 是 target 对象的代理对象**/ public Object getProxyInstance() { //1. 创建一个工具类 Enhancer enhancer = new Enhancer(); //2. 设置父类 enhancer.setSuperclass(target.getClass()); //3. 设置回调函数 enhancer.setCallback(this); //4. 创建子类对象,即代理对象 return enhancer.create(); } /** 重写 intercept 方法,会调用目标对象的方法**/ @Override public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable { // TODO Auto-generated method stub System.out.println("Cglib代理模式 ~~ 开始"); Object returnVal = method.invoke(target, args); System.out.println("Cglib代理模式 ~~ 提交"); return returnVal; } }

    被代理的类

    public class TeacherDao { public String teach() { System.out.println(" 老师授课中 , 我是cglib代理,不需要实现接口 "); return "hello"; } }
    Processed: 0.021, SQL: 9