博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
动态代理 (CGLIB 动态代理)
阅读量:562 次
发布时间:2019-03-09

本文共 11178 字,大约阅读时间需要 37 分钟。

动态代理 代理类在程序运行时被创建,这种代理方式称为动态代理

动态代理实现有两种方式,JDK 动态代理和 CGlib 动态代理,本文介绍 CGlib 动态代理

CGLib 动态代理:采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用,并在调用中添加横切逻辑

 

CGLib 动态代理示例代码

创建一个普通 maven 工程,引入  CGLib 依赖

4.0.0
com.cglibdynamicproxy
cglibdynamicproxy
0.0.1-SNAPSHOT
cglibdynamicproxy
cglib
cglib
3.2.5
maven-compiler-plugin
1.8
1.8

创建被代理类

package com.cglibdynamicproxy.service;/** * 被代理类 * @author Administrator */public class AgentTarget {		public void proxyMethod() {		System.out.println("被代理的方法执行了");;	}}

创建 CglibMethodInterceptor 类,实现 MethodInterceptor

package com.cglibdynamicproxy.cglib;import java.lang.reflect.Method;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CglibMethodInterceptor implements MethodInterceptor{	/**	 * 拦截父类所有方法的调用	 */	@Override	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {		//obj  目标类的实例		//method  目标类方法的反射对象		//args  方法的动态入参		//proxy  代理类实例		System.out.println("before");                Object res = null;                try{        	        //反射调用目标对象方法                    res = proxy.invokeSuper(obj, args);                }catch (Exception e){                    System.out.println("e:" + e.getMessage());                    throw e;                }finally {                    System.out.println("after");                }                return res;	}}

测试类

package com.cglibdynamicproxy;import com.cglibdynamicproxy.cglib.CglibMethodInterceptor;import com.cglibdynamicproxy.service.AgentTarget;import net.sf.cglib.core.DebuggingClassWriter;import net.sf.cglib.proxy.Enhancer;public class CglibDynamicProxyMain {	public static void main(String[] args) {            //将生成的class文件保存到指定目录,这里是项目目录                       System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\\workspace\\cglibdynamicproxy");            Enhancer enhancer = new Enhancer();            //设置父类            enhancer.setSuperclass(AgentTarget.class);            //设置回调函数            enhancer.setCallback(new CglibMethodInterceptor());            //创建AgentTarget.class的子类            AgentTarget childAgentTarget = (AgentTarget) enhancer.create();            //调用方法            childAgentTarget.proxyMethod();	}}

运行如下

生成的 class 文件

重点看生成的这个文件 AgentTarget$$EnhancerByCGLIB$$303de0ca.class

代码如下

package com.cglibdynamicproxy.service;import java.lang.reflect.Method;import net.sf.cglib.core.ReflectUtils;import net.sf.cglib.core.Signature;import net.sf.cglib.proxy.Callback;import net.sf.cglib.proxy.Factory;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class AgentTarget$$EnhancerByCGLIB$$303de0ca extends AgentTarget implements Factory {	private boolean CGLIB$BOUND;	public static Object CGLIB$FACTORY_DATA;	private static final ThreadLocal CGLIB$THREAD_CALLBACKS;	private static final Callback[] CGLIB$STATIC_CALLBACKS;	private MethodInterceptor CGLIB$CALLBACK_0;	private static Object CGLIB$CALLBACK_FILTER;	private static final Method CGLIB$proxyMethod$0$Method;	private static final MethodProxy CGLIB$proxyMethod$0$Proxy;	private static final Object[] CGLIB$emptyArgs;	private static final Method CGLIB$equals$1$Method;	private static final MethodProxy CGLIB$equals$1$Proxy;	private static final Method CGLIB$toString$2$Method;	private static final MethodProxy CGLIB$toString$2$Proxy;	private static final Method CGLIB$hashCode$3$Method;	private static final MethodProxy CGLIB$hashCode$3$Proxy;	private static final Method CGLIB$clone$4$Method;	private static final MethodProxy CGLIB$clone$4$Proxy;	static void CGLIB$STATICHOOK1() {		CGLIB$THREAD_CALLBACKS = new ThreadLocal();		CGLIB$emptyArgs = new Object[0];		Class var0 = Class.forName("com.cglibdynamicproxy.service.AgentTarget$$EnhancerByCGLIB$$303de0ca");		Class var1;		CGLIB$proxyMethod$0$Method = ReflectUtils.findMethods(new String[]{"proxyMethod", "()V"},				(var1 = Class.forName("com.cglibdynamicproxy.service.AgentTarget")).getDeclaredMethods())[0];		CGLIB$proxyMethod$0$Proxy = MethodProxy.create(var1, var0, "()V", "proxyMethod", "CGLIB$proxyMethod$0");		Method[] var10000 = ReflectUtils.findMethods(				new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I",						"clone", "()Ljava/lang/Object;"},				(var1 = Class.forName("java.lang.Object")).getDeclaredMethods());		CGLIB$equals$1$Method = var10000[0];		CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");		CGLIB$toString$2$Method = var10000[1];		CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");		CGLIB$hashCode$3$Method = var10000[2];		CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");		CGLIB$clone$4$Method = var10000[3];		CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");	}	final void CGLIB$proxyMethod$0() {		super.proxyMethod();	}	public final void proxyMethod() {		MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;		if (this.CGLIB$CALLBACK_0 == null) {			CGLIB$BIND_CALLBACKS(this);			var10000 = this.CGLIB$CALLBACK_0;		}		if (var10000 != null) {			var10000.intercept(this, CGLIB$proxyMethod$0$Method, CGLIB$emptyArgs, CGLIB$proxyMethod$0$Proxy);		} else {			super.proxyMethod();		}	}	final boolean CGLIB$equals$1(Object var1) {		return super.equals(var1);	}	public final boolean equals(Object var1) {		MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;		if (this.CGLIB$CALLBACK_0 == null) {			CGLIB$BIND_CALLBACKS(this);			var10000 = this.CGLIB$CALLBACK_0;		}		if (var10000 != null) {			Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);			return var2 == null ? false : (Boolean) var2;		} else {			return super.equals(var1);		}	}	final String CGLIB$toString$2() {		return super.toString();	}	public final String toString() {		MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;		if (this.CGLIB$CALLBACK_0 == null) {			CGLIB$BIND_CALLBACKS(this);			var10000 = this.CGLIB$CALLBACK_0;		}		return var10000 != null				? (String) var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy)				: super.toString();	}	final int CGLIB$hashCode$3() {		return super.hashCode();	}	public final int hashCode() {		MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;		if (this.CGLIB$CALLBACK_0 == null) {			CGLIB$BIND_CALLBACKS(this);			var10000 = this.CGLIB$CALLBACK_0;		}		if (var10000 != null) {			Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);			return var1 == null ? 0 : ((Number) var1).intValue();		} else {			return super.hashCode();		}	}	final Object CGLIB$clone$4() throws CloneNotSupportedException {		return super.clone();	}	protected final Object clone() throws CloneNotSupportedException {		MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;		if (this.CGLIB$CALLBACK_0 == null) {			CGLIB$BIND_CALLBACKS(this);			var10000 = this.CGLIB$CALLBACK_0;		}		return var10000 != null				? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy)				: super.clone();	}	public static MethodProxy CGLIB$findMethodProxy(Signature var0) {		String var10000 = var0.toString();		switch (var10000.hashCode()) {			case -508378822 :				if (var10000.equals("clone()Ljava/lang/Object;")) {					return CGLIB$clone$4$Proxy;				}				break;			case -472693722 :				if (var10000.equals("proxyMethod()V")) {					return CGLIB$proxyMethod$0$Proxy;				}				break;			case 1826985398 :				if (var10000.equals("equals(Ljava/lang/Object;)Z")) {					return CGLIB$equals$1$Proxy;				}				break;			case 1913648695 :				if (var10000.equals("toString()Ljava/lang/String;")) {					return CGLIB$toString$2$Proxy;				}				break;			case 1984935277 :				if (var10000.equals("hashCode()I")) {					return CGLIB$hashCode$3$Proxy;				}		}		return null;	}	public AgentTarget$$EnhancerByCGLIB$$303de0ca() {		CGLIB$BIND_CALLBACKS(this);	}	public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {		CGLIB$THREAD_CALLBACKS.set(var0);	}	public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {		CGLIB$STATIC_CALLBACKS = var0;	}	private static final void CGLIB$BIND_CALLBACKS(Object var0) {		AgentTarget$$EnhancerByCGLIB$$303de0ca var1 = (AgentTarget$$EnhancerByCGLIB$$303de0ca) var0;		if (!var1.CGLIB$BOUND) {			var1.CGLIB$BOUND = true;			Object var10000 = CGLIB$THREAD_CALLBACKS.get();			if (var10000 == null) {				var10000 = CGLIB$STATIC_CALLBACKS;				if (CGLIB$STATIC_CALLBACKS == null) {					return;				}			}			var1.CGLIB$CALLBACK_0 = (MethodInterceptor) ((Callback[]) var10000)[0];		}	}	public Object newInstance(Callback[] var1) {		CGLIB$SET_THREAD_CALLBACKS(var1);		AgentTarget$$EnhancerByCGLIB$$303de0ca var10000 = new AgentTarget$$EnhancerByCGLIB$$303de0ca();		CGLIB$SET_THREAD_CALLBACKS((Callback[]) null);		return var10000;	}	public Object newInstance(Callback var1) {		CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});		AgentTarget$$EnhancerByCGLIB$$303de0ca var10000 = new AgentTarget$$EnhancerByCGLIB$$303de0ca();		CGLIB$SET_THREAD_CALLBACKS((Callback[]) null);		return var10000;	}	public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {      CGLIB$SET_THREAD_CALLBACKS(var3);      AgentTarget$$EnhancerByCGLIB$$303de0ca var10000 = new AgentTarget$$EnhancerByCGLIB$$303de0ca;      switch(var1.length) {      case 0:         var10000.
(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; default: throw new IllegalArgumentException("Constructor not found"); } } public Callback getCallback(int var1) { CGLIB$BIND_CALLBACKS(this); MethodInterceptor var10000; switch (var1) { case 0 : var10000 = this.CGLIB$CALLBACK_0; break; default : var10000 = null; } return var10000; } public void setCallback(int var1, Callback var2) { switch (var1) { case 0 : this.CGLIB$CALLBACK_0 = (MethodInterceptor) var2; default : } } public Callback[] getCallbacks() { CGLIB$BIND_CALLBACKS(this); return new Callback[]{this.CGLIB$CALLBACK_0}; } public void setCallbacks(Callback[] var1) { this.CGLIB$CALLBACK_0 = (MethodInterceptor) var1[0]; } static { CGLIB$STATICHOOK1(); }}

其中,这段代码为核心内容

public final void proxyMethod() {		MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;		if (this.CGLIB$CALLBACK_0 == null) {			CGLIB$BIND_CALLBACKS(this);			var10000 = this.CGLIB$CALLBACK_0;		}		if (var10000 != null) {			var10000.intercept(this, CGLIB$proxyMethod$0$Method, CGLIB$emptyArgs, CGLIB$proxyMethod$0$Proxy);		} else {			super.proxyMethod();		}	}

程序运行流程:代理对象继承父类 AgentTarget,重写 proxyMethod 方法,拦截器调用 intercept 方法,intercept 方法由自定义的 CglibMethodInterceptor 实现,当调用 MyMethodInterceptor 中的 intercept 方法时,通过反射调用目标对象方法,从而完成了由代理对象访问到目标对象的动态代理

 

转载地址:http://xompz.baihongyu.com/

你可能感兴趣的文章