本文共 11101 字,大约阅读时间需要 37 分钟。
定义
为其他对象提供一种代理以控制对这个对象的访问在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介作用
作用
不改变原来的代码,而增强原类对象的功能,主要是做方法的增强!!!可以选择前置、后置、环绕、异常处理增强应用场景
Spring AOP、Spring事务管理…由程序员创建或由特定工具自动生成代理类源代码,再对其编译。在程序运行之前,就知道需要对哪一个类进行代理,代理类的.class文件就已经存在
类图
土豪TuHao通过中间经纪人BrokerProxy约会苍老师TeacherCangImplGirl接口类:
public interface Girl { /** * 约会 * @param length 身高 * @return */ boolean dating(float length);}
苍老师实现类:
public class TeacherCangImpl implements Girl { @Override public boolean dating(float length) { if (length >= 1.7F) { System.out.println("身高可以,可以约!"); } System.out.println("身高不可以,不可约!"); return false; }}
代理类:
public class BrokerProxy implements Girl{ /** * 经纪人必须持有女孩子 */ private Girl girl; public Girl getGirl() { return girl; } public void setGirl(Girl girl) { this.girl = girl; } @Override public boolean dating(float length) { System.out.println("静态代理模式:前置增强,老板,这个我试过了,很不错,推荐给你!"); boolean flag = this.getGirl().dating(length); System.out.println("静态代理模式:后置增强,老板,你觉得怎样,欢迎下次再约!"); return flag; }}
土豪类:
public class TuHao { private float length; public TuHao(float length) { this.length = length; } public void dating(Girl girl) { girl.dating(length); }}
测试类:
@Controller@RequestMapping("/proxy")public class ProxyTestController { /** * @return */ @RequestMapping("/statical.json") @ResponseBody public String statical() { TuHao th = new TuHao(1.7F); Girl tc = new TeacherCangImpl(); //土豪通过经纪人约会苍老师 BrokerProxy proxy = new BrokerProxy(); proxy.setGirl(tc); th.dating(proxy); return "proxy statical success"; }}
缺点
代理类在程序运行时,运用反射机制动态创建而成。
静态代理事先知道代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道
JDK动态代理只可对接口创建代理
核心类介绍
Proxy类:提供了用于创建动态代理类和实例对象的方法,它是所创建的动态代理类的父类,它最常用的方法如下
- public static Class<?> getProxyClass(ClassLoader loader,Class<?>… interfaces):该方法用于返回一个Class类型的代理类,在参数中需要提供类加载器并需要指定代理的接口数组(与真实主题类的接口列表一致)
- public static Object newProxyInstance(ClassLoader loader, Class<?>[]interfaces, InvocationHandler h):该方法用于返回一个动态创建的代理类的实例,方法中第一个参数loader表示代理类的类加载器,第二个参数interfaces表示代理类所实现的接口列表(与真实主题类的接口列表一致),第三个参数h表示所指派的调用处理程序类
InvocationHandler接口:代理处理程序类的实现接口,该接口作为代理实例的调用处理者的公共父类,每一个代理类的实例都可以提供一个相关的具体调用处理者(InvocationHandler接口的子类)。在该接口中声明了如下方法
- public Object invoke(Objectproxy, Method method, Object[] args):该方法用于处理对代理类实例的方法调用并返回相应的结果,当一个代理实例中的业务方法被调用时将自动调用该方法。invoke()方法包含三个参数,其中第一个参数proxy表示代理类的实例,第二个参数method表示需要代理的方法,第三个参数args表示代理方法的参数数组
动态代理类需要在运行时指定所代理真实主题类的接口,客户端在调用动态代理对象的方法时,调用请求会将请求自动转发给InvocationHandler对象的invoke()方法,由invoke()方法来实现对请求的统一处理。
类图
代码示例 被代理的接口(人):public interface IPepole { /** * 是人都要吃饭 */ void eat(); /** * 是人都有职业 */ void career();}
被代理的接口实现类(教师):
public class TeacherService implements IPepole { @Override public void eat() { System.out.println("TeacherService eat"); } @Override public void career() { System.out.println("TeacherService career"); }}
被代理的接口(学生):
public class StudentService implements IPepole { @Override public void eat() { System.out.println("StudentService eat"); } @Override public void career() { System.out.println("StudentService career"); }}
功能增强实现类:
public class JDKInvocationHandler implements InvocationHandler { private Object object; public JDKInvocationHandler(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("jdk动态代理调用之前的处理"); method.invoke(object, args); System.out.println("jdk动态代理调用之后的处理"); return null; }}
创建代理对象的类:
public class JDKProxyInstanceFactory { public static Object proxy(Object target) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new JDKInvocationHandler(target) ); }}
测试类:
@Controller@RequestMapping("/proxy")public class ProxyTestController { /** * JDK动态代理测试 * JDK动态代理只能为接口创建代理实例 * @return */ @RequestMapping("/jdkDynamicProxy.json") @ResponseBody public String jdkDynamicProxy() { IPepole teacher = (IPepole) JDKProxyInstanceFactory.proxy(new TeacherService()); teacher.eat(); teacher.career(); IPepole student = (IPepole) JDKProxyInstanceFactory.proxy(new StudentService()); student.eat(); student.career(); return "jdk dynamic proxy success"; }}
测试结果:
jdk动态代理调用之前的处理TeacherService eatjdk动态代理调用之后的处理jdk动态代理调用之前的处理TeacherService careerjdk动态代理调用之后的处理jdk动态代理调用之前的处理StudentService eatjdk动态代理调用之后的处理jdk动态代理调用之前的处理StudentService careerjdk动态代理调用之后的处理
生成代理类
jdk动态代理类是动态生成的.class,会缓存在内存中。除此之外,我们也可以自己手动生成.class文件到本地,方式如下(主要使用JDK自带的ProxyGenerator方法):byte[] data = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{ IPepole.class});try { FileOutputStream out = new FileOutputStream("D:\\$Proxy0.class"); out.write(data); out.close();} catch (FileNotFoundException e) { e.printStackTrace();} catch (IOException e) { e.printStackTrace();}
生成后的代码反编译结果:
import com.dalomao.spring.aop.Pepole;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements Pepole{ private static Method m1; private static Method m4; private static Method m2; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); } public final boolean equals(Object paramObject) throws { try { return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final void eat() throws { try { this.h.invoke(this, m4, null); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final String toString() throws { try { return (String)this.h.invoke(this, m2, null); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final void sleep() throws { try { this.h.invoke(this, m3, null); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } public final int hashCode() throws { try { return ((Integer)this.h.invoke(this, m0, null)).intValue(); } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m4 = Class.forName("com.dalomao.spring.aop.Pepole").getMethod("eat", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m3 = Class.forName("com.dalomao.spring.aop.Pepole").getMethod("sleep", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); return; } catch (NoSuchMethodException localNoSuchMethodException) { throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); } catch (ClassNotFoundException localClassNotFoundException) { } throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); }}
CGLIB动态代理可对接口、具体类创建代理
CGLIB是一个高层次的java字节码生成和转换的api库。常在AOP、ORM框架中用来生成动态代理对象、拦截属性访问
学习网址:
maven中可以引入:
cglib cglib 3.2.6
类图
代码实例 功能增强实现类:public class CglibMethodInterceptor implements MethodInterceptor { private Object target; public CglibMethodInterceptor(Object target) { this.target = target; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //前置增强 System.out.println("cglib interfrace before"); Object res = null;//返回值 //调用父类的该方法,如果是生成接口的代理时不可调用 //res = methodProxy.invokeSuper(proxy, args); //通过method来调用被代理对象的方法 if (this.target != null) { res = method.invoke(target, args); } //后置增强 System.out.println("cglib interfrace after"); return null; }}
测试类:
@Controller@RequestMapping("/proxy")public class ProxyTestController { /** * cglib动态代理测试 * cglib可以为接口,也可以为实现类创建代理实例 * @return */ @RequestMapping("/cglibDynamicProxy.json") @ResponseBody public String cglibDynamicProxy() { /** * 为接口创建代理 */ Enhancer enhancer1 = new Enhancer(); enhancer1.setCallback(new CglibMethodInterceptor(new StudentService()));//设置增强回调 enhancer1.setInterfaces(new Class[]{ IPepole.class});//对接口生成代理对象 IPepole proxy1 = (IPepole) enhancer1.create(); proxy1.eat(); proxy1.career(); /** * 为实体类创建代理 */ Enhancer enhancer2 = new Enhancer(); enhancer2.setCallback(new CglibMethodInterceptor(new TeacherService())); enhancer2.setSuperclass(TeacherService.class);//对类生成代理对象 enhancer2.setInterfaces(null); //当有多个callback时,需要通过callbackFilter来指定被代理方法使用第几个callback /* enhancer2.setCallbackFilter(new CallbackFilter() { @Override public int accept(Method method) { return 0; } }); */ TeacherService proxy2 = (TeacherService) enhancer2.create(); proxy2.eat(); proxy2.career(); return "cglib dynamic proxy success"; }}
结果:
cglib interfrace beforeStudentService eatcglib interfrace aftercglib interfrace beforeStudentService careercglib interfrace aftercglib interfrace beforeTeacherService eatcglib interfrace aftercglib interfrace beforeTeacherService careercglib interfrace after
转载地址:http://cwpxi.baihongyu.com/