设计模式之代理模式
Posted 项羽齐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之代理模式相关的知识,希望对你有一定的参考价值。
使用聚合模式实现静态代理
本质上,动态代理是在程序运行过程中创建生成一个类并且将它加载到JVM中,通过上面的实现步骤,他是把额外的代码(spring中叫切面)植入到被代理类(方法)中以后合成一个类。与静态代理的实现是一样的.
静态代理:在编译时创建代理类。代理类和方法都是固定的。不可改变。
每个代理类都需要实现该接口方法。
1、定义接口
package cn.xiang.proxy; public interface HelloWorld { void sysHello(); }
2、实现接口,被代理类
package cn.xiang.proxy; public class HelloWorldImpl implements HelloWorld{ @Override public void sysHello() { System.out.println("HelloWordImpl --> sysHello() --> start"); System.out.println("HelloWordImpl --> sysHello() --> end"); } }
3、创建代理类
package cn.xiang.proxy; public class HelloWorldProxy implements HelloWorld{ private HelloWorld helloWord; public HelloWorldProxy(HelloWorld helloword) { this.helloWord = helloword; } @Override public void sysHello() { System.out.println("HelloWordproxy sysHello() --> start"); helloWord.sysHello(); System.out.println("HelloWordproxy sysHello() --> end"); } }
4、调用代理类实现静态代理
public class Action { public static void main(String[] args) { new HelloWorldProxy(new HelloWorldImpl2()).sysHello(); } }
动态代理
在运行时动态创建代理对象,对象和方法都不是固定的。
1、创建接口
public interface HelloWorld { void sysHello(); }
2、创建被代理对象,实现接口
public class HelloWorldImpl implements HelloWorld{ @Override public void sysHello() { System.out.println("HelloWordImpl --> sysHello() --> start"); System.out.println("HelloWordImpl --> sysHello() --> end"); } }
3、创建动态代理生成对象。实现InvocationHandler接口
public class HelloWorldProxy implements InvocationHandler{ private HelloWorld helloWord; public HelloWorldProxy(HelloWorld helloword) { this.helloWord = helloword; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("动态生成代理对象--开始"); Object obj = method.invoke(helloWord, args); System.out.println("动态生成代理对象--成功"); return obj; } }
5、动态调用生成动态代理对象,并执行动态方法
public class Action { public static void main(String[] args) { HelloWorldImpl hwi = new HelloWorldImpl(); HelloWorld hw = (HelloWorld) Proxy.newProxyInstance(hwi.getClass().getClassLoader(), hwi.getClass().getInterfaces(), new HelloWorldProxy(hwi)); hw.sysHello(); } }
cglib方式
CGLib不能对声明为final的方法和类进行代理,因为CGLib原理是动态生成被代理类的子类。
1. 得到的代理对象其实是被代理对象的子类
2. 代理对象重写了被代理对象的所有方法,我们调用的时候其实是调用的被代理对象的重写方法
1、需要导入cglib包
<dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>3.2.6</version> </dependency>
2、创建实现类
定义一个拦截器。在调用目标方法时,CGLib会回调MethodInterceptor接口方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。
public class HelloWorldImpl { public void sysHello(String name) { System.out.println("HelloWordImpl --> sysHello() --> start"); System.out.println("name="+name); System.out.println("HelloWordImpl --> sysHello() --> end"); } }
3、创建动态代理类
参数:Object为由CGLib动态生成的代理类实例,Method为上文中实体类所调用的被代理的方法引用,Object[]为参数值列表,MethodProxy为生成的代理类对方法的代理引用。
返回:从代理实例的方法调用返回的值。
其中,proxy.invokeSuper(obj,arg):
调用代理类实例上的proxy方法的父类方法(即实体类HelloWorldImpl中对应的方法)
public class HelloWorldProxy implements MethodInterceptor{ @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object obj = proxy.invokeSuper(object, args); return obj; } }
4、调用实现
这里Enhancer类是CGLib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展,以后会经常看到它。
首先将被代理类HelloWorldImpl设置成父类,
然后设置拦截器HelloWorldProxy,
最后执行enhancer.create()动态生成一个代理类,
并从Object强制转型成父类型HelloWorldImpl。
public class Action { public static void main(String[] args) { Enhancer en = new Enhancer(); en.setSuperclass(HelloWorldImpl.class); en.setCallback( new HelloWorldProxy()); HelloWorldImpl hw = (HelloWorldImpl)en.create(); hw.sysHello("xiangyuqi"); } }
输出结果:
以上是关于设计模式之代理模式的主要内容,如果未能解决你的问题,请参考以下文章