JavaDemo——使用CGLIB动态代理

cglib动态代理和jdk动态代理是java中常用的两种动态代理;

  • cglib动态代理:基于继承机制,可以代理类或接口,不能代理final类和方法,采用ASM字节码框架生成子类,性能好,占用内存多;
  • jdk动态代理:基于接口反射机制,必须依赖接口,使用反射,有一定性能消耗,占内存低;

cglib使用方法:

  1. 先maven导入:

    <dependency>

    <groupId>cglib</groupId>

    <artifactId>cglib</artifactId>

    <version>3.3.0</version>

    </dependency>

  2. 实例化一个Enhancer对象;
  3. 使用setSuperclass()或者setInterfaces()设置代理类或接口;
  4. 使用setCallback()设置代理方法,或者setCallbacks()和setCallbackFilter()搭配使用;

关于public void setCallback(final Callback callback)的参数Callback接口:

  • NoOp:使用NoOp.INSTANCE表示直接调用原始方法;
  • MethodInterceptor:比较常用增强方法,可以使用参数MethodProxy的invokeSuper()方法调用父类方法,直接使用索引方式绕过反射,提升性能;(返回值为方法返回值)
  • FixedValue:直接返回固定值;(返回值为方法返回值)
  • LazyLoader:只会在第一次的时候调用,后续复用该对象;(返回值为真实代理对象)
  • Dispatcher:每次调用都会生成新的对象;(返回值为真实代理对象)
  • ProxyRefDispatcher:类似Dispatcher,不过可以从参数里获得proxy对象;(返回值为真实代理对象)
  • InvocationHandler:类似jdk的动态代理,参数里没有MethodProxy,只能使用method.invoke()反射调用;(返回值为方法返回值)

关于public void setCallbackFilter(CallbackFilter filter)的参数CallbackFilter接口:

实现int accept(Method method)方法,返回值为public void setCallbacks(Callback[] callbacks)参数中数组的索引,可以根据Method条件返回不同的索引从而调用Callback[]中不同索引的回调方法;

测试代码:

测试类ABC.java:

package testcglib;

public class ABC {
	
	private String str;
	
	public ABC(String s) {
		System.out.println("newABC,s=" + s);
		this.str = s;
	}

	public void a() {
		System.out.println("ABC -> a()");
	}
	
	public void b() {
		System.out.println("ABC -> b()");
	}
	
	public String c(String arg) {
		return this.str + arg;
	}
	
	public int d(int x, int y) {
		return x + y;
	}
	
	public void lazyloader() {
		
	}
	
	public void dispatcher() {
		System.out.println("ABC -> dispatcher()");
	}
	
	public void testProxydispatcher() {
		System.out.println("ABC -> proxydispatcher()");
	}
}

ABC.java的子类ChABC.java:

package testcglib;

public class ChABC extends ABC {

	public ChABC(String s) {
		super(s);
		System.out.println("newChABC(" + s + ")");
	}
	
	@Override
	public void a() {
		System.out.println("ChABC -> a()");
	}
	
	@Override
	public void lazyloader() {
		System.out.println("chabc -> lazyloader()");
	}
	
	@Override
	public void dispatcher() {
		System.out.println("chabc -> dispatcher()");
	}

}

测试主类:

/**
 * 2025年7月10日14:18:07
 */
package testcglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Dispatcher;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.FixedValue;
import net.sf.cglib.proxy.InvocationHandler;
import net.sf.cglib.proxy.LazyLoader;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.NoOp;
import net.sf.cglib.proxy.ProxyRefDispatcher;

/**
 * @author XWF
 */
public class TestCGLIB {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Enhancer enhancer = new Enhancer();
		// 设置代理类或者接口
		enhancer.setSuperclass(ABC.class);
//		enhancer.setInterfaces(new Class[] {});
		// 设置代理方法
//		enhancer.setCallback(null);
		enhancer.setCallbacks(new Callback[] {
				NoOp.INSTANCE, // 第0个,调用原方法
				new MethodInterceptor() { // 第1个代理方法
					@Override
					public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
						System.out.println("1-callback-method:" + method.getName());
						System.out.println("1-before");
						int a = (int) args[0];
						int b = (int) args[1];
						args[0] = a * 10;
						args[1] = b * 10;
						return proxy.invokeSuper(obj, args); // 返回方法结果(使用直接索引绕过反射)
					}
				},
				new MethodInterceptor() { // 第2个代理方法
					@Override
					public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
						System.out.println("2-callback-method:" + method.getName());
						System.out.println("2-before");
						Object res = proxy.invokeSuper(obj, args);
						System.out.println("2-after");
						return res;
					}
				},
				new FixedValue() { // 第3个,直接返回固定值
					@Override
					public Object loadObject() throws Exception {
						System.out.println("3-fixedvalue");
						return "FIXED"; // 返回方法结果
					}
				},
				new InvocationHandler() { // 4 跟JDK的动态代理类似
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						return method.invoke(proxy, args); // 返回方法结果(反射)
					}
				},
				new LazyLoader() { // 5 只第一次调用一次
					@Override
					public Object loadObject() throws Exception {
						return new ChABC("LazyLoader"); // 返回真实代理对象,第一次生成,后续调用复用
					}
				},
				new Dispatcher() { // 6 每次都调用
					@Override
					public Object loadObject() throws Exception {
						return new ABC("Dispatcher"); // 返回真实代理对象,每次都生成新的
					}
				},
				new ProxyRefDispatcher() { // 7 相比Dispatcher,可以拿到proxy对象
					@Override
					public Object loadObject(Object proxy) throws Exception {
						System.out.println("7-proxy:" + proxy.getClass());
						return new ChABC("proxy"); // 返回真实代理对象
					}
				}
		});
		// 指定调用哪个代理方法
		enhancer.setCallbackFilter(new CallbackFilter() {
			@Override
			public int accept(Method method) { // 返回值为调用回调方法的索引
				if("a".equals(method.getName())) { // 名字为“a”的方法调用第0个
					return 0;
				} else if("c".equals(method.getName())) { // 名字为“c”的方法调用第3个
					return 3;
				} else if("d".equals(method.getName())) { // 名字为“d”的方法调用第1个
					return 1;
				} else if("lazyloader".equals(method.getName())) {
					return 5;
				} else if("dispatcher".equals(method.getName())) {
					return 6;
				} else if("testProxydispatcher".equals(method.getName())) {
					return 7;
				} else { // 其余方法都调用第2个
					return 2;
				}
			}
		});
		
//		ABC obj = (ABC) enhancer.create(); // 使用无参构造方法
		System.out.println("  使用有参构造方法");
		ABC obj = (ABC) enhancer.create(new Class[] {String.class}, new Object[] {"abc"});
		System.out.println("  调用a方法");
		obj.a(); // 直接调用原方法
		System.out.println("  调用b方法");
		obj.b();
		System.out.println("  调用c方法");
		System.out.println("c()返回:" + obj.c("xyz")); // 返回固定值
		System.out.println("  调用d方法");
		System.out.println("d()返回:" + obj.d(2, 3));
		System.out.println("  调用lazyloader方法");
		obj.lazyloader(); // 第一次new
		obj.lazyloader();
		obj.lazyloader();
		System.out.println("  调用dispatcher方法");
		obj.dispatcher(); // 每次都new
		obj.dispatcher();
		obj.dispatcher();
		System.out.println("  调用testProxydispatcher方法");
		obj.testProxydispatcher(); // 每次都new
		obj.testProxydispatcher();
	}
	
}

执行结果:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值