Java设计模式——代理模式

代理模式 学习目标

掌握代理模式的应用场景和实现原理。

应用场景

保护目标对象:客户并不知道对象是如何实现具体业务功能的,只要调用代理对象的接口就行了。

增强目标对象:在实现目标对象的业务功能之前或者之后做一些业务实现。Spring-AOP

实现原理

静态代理:代理对象持有被代理对象的引用。由被代理对象实现目标业务。

动态代理:代理对象持有被代理对象的引用,代码运行产生一个新的java类,并被编译重新加载,然后在新的类中执行目标业务实现动态代理。

了解静态代理和动态代理的区别。

静态代理:被代理对象在代码中被写死了,不易扩展,适用于简单的业务,代码复用性不高,违背开闭原则。

动态代理:只要是实现了同一个接口的被代理类,都可以代理实现,实现了业务扩展。代码复用,遵循开闭原则。

了解CGLib和JDK-proxy的区别。

JDK-proxy动态代理:实现了被代理对象的接口,生成新的class字节码,利用反射调用实现代理。无法代理不实现代理业务接口的方法。

CGLib动态代理:继承被代理对象,生成新的class字节码,通过fastclass机制调用实现代理。无法代理被final关键字修饰的方法

代理模式的定义

为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和服务端起到中介的作用。是一种结构型设计模式

静态代理 /** * @description: 被代理对象需要实现的目标接口 * @author: lmc * @create: 2019-06-12 15:38 **/ public interface ITarget { /** * @description: 被代理对象的行为 * @return void * @date 2019/6/12 15:39 * @author lmc */ void behavior(); } /** * @description: 真实的被代理的目标对象 * @author: lmc * @create: 2019-06-12 15:41 **/ public class TargetImpl implements ITarget { public void behavior() { System.out.println("执行真实的被代理对象的行为。"); } }

下面的类也是一个被代理的目标对象,但是没有实现ITarget接口

/** * @description: 真实的被代理的目标对象 * @author: lmc * @create: 2019-06-12 15:41 **/ public class Target{ public void behavior() { System.out.println("执行被代理对象target的行为。"); } } /** * @description: 静态代理类 * @author: lmc * @create: 2019-06-12 15:45 **/ public class StaticProxy { /** * 持有被代理对象的引用 */ private ITarget targetImpl; /** * 持有被代理对象的引用 */ private Target target;//一个没有实现接口的类 /** * 构造方法初始化值 * @param targetImpl */ public StaticProxy(ITarget targetImpl,Target target){ this.targetImpl=targetImpl; this.target=target; } /** * @description: 被代理之前的增强行为 * @date 2019/6/12 15:56 * @author lmc */ private void beforeBehavior(){ System.out.println("执行代理之前需要做的一些事情。"); } /** * @description: 被代理之后的增强行为 * @date 2019/6/12 15:57 * @author lmc */ private void afterBehavior(){ System.out.println("执行代理之后需要做的一些事情。"); } /** * @description: 开始执行代理 * @date 2019/6/12 15:59 * @author lmc */ public void startProxy(){ beforeBehavior(); targetImpl.behavior(); target.behavior(); afterBehavior(); } } /** * @description: 静态代理客户端 懒汉式单例 * @author: lmc * @create: 2019-06-12 16:01 **/ public class StaticProxyClient implements Serializable { private final static StaticProxyClient staticProxyClient=new StaticProxyClient(); private StaticProxyClient(){ if(null != staticProxyClient){ throw new RuntimeException("单例类,不允许被反射实例化"); } }; public static StaticProxyClient getInstance(){ return staticProxyClient; } /** * @description: 开始静态代理 * @date 2019/6/12 16:20 * @author lmc */ public void startStaticProxy(){ ITarget targetImpl=new TargetImpl(); Target target=new Target(); StaticProxy staticProxy=new StaticProxy(targetImpl,target); staticProxy.startProxy(); } /** * @description: 重写readResolve,防止序列化破坏单例 * @return java.lang.Object * @date 2019/6/12 16:18 * @author lmc */ private Object readResolve(){ return staticProxyClient; } } /** * @description: 静态代理测试 * @author: lmc * @create: 2019-06-12 16:10 **/ public class StaticProxyTest { public static void main(String[] args) { StaticProxyClient.getInstance().startStaticProxy(); } } 静态代理测试结果

Java设计模式——代理模式

只要代理对象持有被代理对象的引用就可以实现静态代理了。

JDK-proxy动态代理 /** * @description: 真实的被代理的目标对象 * @author: lmc * @create: 2019-06-12 15:41 **/ public class TargetImpl1 implements ITarget { public void behavior() { System.out.println("执行被代理对象1的行为。"); } } /** * @description: 真实的被代理的目标对象 * @author: lmc * @create: 2019-06-12 15:41 **/ public class TargetImpl2 implements ITarget { public void behavior() { System.out.println("执行被代理对象2的行为。"); } } /** * @description: 真实的被代理的目标对象 * @author: lmc * @create: 2019-06-12 15:41 **/ public class TargetImpl3 implements ITarget { public void behavior() { System.out.println("执行被代理对象3的行为。"); } } /** * @description: JDK动态代理对象 * @author: lmc * @create: 2019-06-12 17:00 **/ public class JdkProxy implements InvocationHandler { /** * 被代理对象的引用 */ private ITarget target; /** * @description: 获取代理之后的实例对象 * @param target 被代理对象 * @return com.lmc.gp12380.pattern.proxy.ITarget * @date 2019/6/12 19:55 * @author lmc */ public ITarget getProxyInstance(ITarget target){ this.target = target; Class<?> clazz = target.getClass(); return (ITarget) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforeBehavior(); //通过反编译工具可以查看源代码 byte [] bytes = ProxyGenerator.generateProxyClass("$Proxy0",new Class[]{ITarget.class}); FileOutputStream os = new FileOutputStream("E://$Proxy0.class"); os.write(bytes); os.close(); Object obj = method.invoke(this.target,args); afterBehavior(); return obj; } /** * @description: 被代理之前的增强行为 * @date 2019/6/12 15:56 * @author lmc */ private void beforeBehavior(){ System.out.println("执行代理之前需要做的一些事情。"); } /** * @description: 被代理之后的增强行为 * @date 2019/6/12 15:57 * @author lmc */ private void afterBehavior(){ System.out.println("执行代理之后需要做的一些事情。"); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxjjs.html