JAVA-动态代理CGLIB

CGLIB动态代理实现也是常用的实现方式,相对于JDK的只能代理接口,CGLIB的可以直接对类进行代理,功能也更多

1. 由于实现原理,需要一个类

public class OrderService {
	
	public String add(String orderNo)  {
		System.out.println("add a order[orderNo=" + orderNo + "]");
                 // 后续测试使用
                 delete(orderNo);
		return "success";
	}
	
	public String delete(String orderNo)  {
		System.out.println("delete a order[orderNo=" + orderNo + "]");
		return "success";
	}
}

 2. InvocationHandler

这种方式和jdk的实现类似,区别在于一个是对接口代理,一个是对类代理

public class OrderInvocationHandler implements InvocationHandler {

	private Object target;
	
	public OrderInvocationHandler(Object target) {
		super();
		this.target = target;
	}

	/**
	 * proxy: OrderService$$EnhancerByCGLIB$$47a95d3e
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("method call before ...");
                // 这样写会造成循环调用
		// Object result = method.invoke(proxy, args);
		Object result = method.invoke(target, args);
		System.out.println("method call after ...");
		return result;
	}
}

2.1 测试

public static void main(String[] args) {
		
    // System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:/BaiduNetdiskDownload/java-sample");
		
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(OrderService.class);
		
    // 自定义InvocationHandler
    enhancer.setCallback(new OrderInvocationHandler(new OrderService()));
		
    // OrderService$$EnhancerByCGLIB$$47a95d3e
    OrderService orderService = (OrderService) enhancer.create();
    System.out.println(orderService.add("111"));
}

输出: 

method call before ...
add a order[orderNo=111]
method call after ...
success

2.2 代理类源码(部分)

public class OrderService$$EnhancerByCGLIB$$47a95d3e extends OrderService implements Factory {

	private InvocationHandler CGLIB$CALLBACK_0;
	private static final Method CGLIB$add$0;

	static void CGLIB$STATICHOOK1() {
		CGLIB$add$0 = Class.forName("com.core.proxy.cglib.OrderService").getDeclaredMethod("add",
				Class.forName("java.lang.String"));
	}

	public final String add(String var1) {
		try {
                         // 此处CGLIB$CALLBACK_0其实就是OrderInvocationHandler实例
			InvocationHandler var10000 = this.CGLIB$CALLBACK_0;
			return (String) var10000.invoke(this, CGLIB$add$0, new Object[]{var1});
		} catch (Error | RuntimeException var2) {
			throw var2;
		} catch (Throwable var3) {
			throw new UndeclaredThrowableException(var3);
		}
	}

	static {
		CGLIB$STATICHOOK1();
	}

 

3. MethodInterceptor 

这种方法可以实现和上面方法同样的功能,唯一区别在于当对代理类(obj)调用invokeSuper方法时,如果出现方法调用(add方法调用delete方法),日志会嵌套打印

public class OrderMethodInterceptor implements MethodInterceptor {

	private Object target;
	
	public OrderMethodInterceptor(Object target) {
		super();
		this.target = target;
	}

	/**
	 * obj		com.core.proxy.cglib.OrderService$$EnhancerByCGLIB$$b4cc9f16@b7dd107
	 * method	public java.lang.String com.core.proxy.cglib.OrderService.add(java.lang.String)
	 * proxy	net.sf.cglib.proxy.MethodProxy@42eca56e
	 * 	createInfo
	 * 		c1 com.core.proxy.cglib.OrderService
	 * 		c2 com.core.proxy.cglib.OrderService$$EnhancerByCGLIB$$b4cc9f16
	 * 	FastClassInfo
	 * 		f1  OrderService$$FastClassByCGLIB$$9ef31016
	 * 			type=com.core.proxy.cglib.OrderService
	 * 		f2	OrderService$$EnhancerByCGLIB$$b4cc9f16$$FastClassByCGLIB$$c22a6914
	 * 			type=OrderService$$EnhancerByCGLIB$$b4cc9f16
	 * 		i1	0(add)
	 * 		i2	18(CGLIB$add$0)
	 */
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		System.out.println("cglib method before...");
	
	        // 对于嵌套函数调用会多次输出日志信息
		// Object result = proxy.invokeSuper(obj, args);
		
		// 这样会出现死循环
		// Object result = proxy.invoke(obj, args);
		
		Object result;
		if (null != target) {
			// 嵌套方法不会多次输出日志信息(目前还想不到其它的应用场景)
                        // f1.i1()
			result = proxy.invoke(target, args);
		} else {
                        // f2.i2()
			result = proxy.invokeSuper(obj, args);
		}
		System.out.println("cglib method after...");
		return result;
	}
}

 3.1 测试

public static void main(String[] args) {
		
    // System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:/BaiduNetdiskDownload/java-sample");
		
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(OrderService.class);
		
    // 自定义MethodInterceptor
    enhancer.setCallback(new OrderMethodInterceptor(new OrderService()));
	
    // OrderService$$EnhancerByCGLIB$$47a95d3e
    OrderService orderService = (OrderService) enhancer.create();
    System.out.println(orderService.add("111"));
}

输出:

cglib method before...
add a order[orderNo=111]
cglib method after...
success

3.2 代理类源码(部分) 


public class OrderService$$EnhancerByCGLIB$$b4cc9f16 extends OrderService implements Factory {

	private static final Method CGLIB$add$0$Method;
	private static final MethodProxy CGLIB$add$0$Proxy;

	static void CGLIB$STATICHOOK1() {
		Class var0 = Class.forName("com.core.proxy.cglib.OrderService$$EnhancerByCGLIB$$b4cc9f16");
		var10000 = ReflectUtils.findMethods(
				new String[]{"add", "(Ljava/lang/String;)Ljava/lang/String;", "delete",
						"(Ljava/lang/String;)Ljava/lang/String;"},
				(var1 = Class.forName("com.core.proxy.cglib.OrderService")).getDeclaredMethods());
		CGLIB$add$0$Method = var10000[0];
		CGLIB$add$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)Ljava/lang/String;", "add",
				"CGLIB$add$0");
	}

        // 调用父类方法
	final String CGLIB$add$0(String var1) {
		return super.add(var1);
	}

        // 被重写的方法
	public final String add(String var1) {
		MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
             /**
	     *  参数说明:
	     * 	    var10000: OrderMethodInterceptor实例
             *	    CGLIB$add$0$Method: add方法
             *	    CGLIB$add$0$Proxy: MethodProxy实例,根据上面定义可知:
             *		c1是OrderService类,最后转化为MethodProxy.invoke方法中的FastClassInfo.f1
             *		c2是OrderService$$EnhancerByCGLIB$$b4cc9f16类,最后转化为MethodProxy.invokeSuper方法中的FastClassInfo.f2
             *		sig1是add方法,最后转化为MethodProxy.invoke方法中的FastClassInfo.i1
             *		sig2是CGLIB$add$0方法,最后转化为MethodProxy.invokeSuper方法中的FastClassInfo.i2
             *		根据参数也就可以明白为什么通常我们使用的都是proxy.invokeSuper(obj, args)方法,而proxy.invoke(obj, args)会出现循环调用的问题
             * */
	    return var10000 != null
				? (String) var10000.intercept(this, CGLIB$add$0$Method, new Object[]{var1}, CGLIB$add$0$Proxy)
				: super.add(var1);
	}

	static {
		CGLIB$STATICHOOK1();
	}
}

4. FixedValue

这种方法用于对所有被代理方法(add或delete)都返回固定值(hello cglib),注意传入的参数会被屏蔽掉,返回值类型要相同,不然会抛类型转换错误异常,比如该例中固定返回值是String类型,调用hashCode(返回值是int)方法会抛异常

public class FixedValueInterceptor implements FixedValue {

	@Override
	public Object loadObject() throws Exception {
		return "hello cglib";
	}

}

4.1 测试

public static void main(String[] args) {
		
    // System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:/BaiduNetdiskDownload/java-sample");
		
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(OrderService.class);
			
    // 对拦截的所有方法都返回相同返回值
    enhancer.setCallback(new FixedValueInterceptor());
			
    // OrderService$$EnhancerByCGLIB$$47a95d3e
    OrderService orderService = (OrderService) enhancer.create();
    System.out.println(orderService.add("111"));
    System.out.println(orderService.hashCode());

}

输出:

hello cglib
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number
	at com.core.proxy.cglib.OrderService$$EnhancerByCGLIB$$c555ee0d.hashCode(<generated>)
	at com.core.proxy.cglib.Test.main(Test.java:41)
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8

 4.2 代理类源码(部分) 

public class OrderService$$EnhancerByCGLIB$$c555ee0d extends OrderService implements Factory {
    
        // 此处CGLIB$CALLBACK_0就是FixedValueInterceptor实例
	private FixedValue CGLIB$CALLBACK_0;
    
        // 方法被重写
	public final String add(String var1) {
	    FixedValue var10000 = this.CGLIB$CALLBACK_0;
	    return (String) var10000.loadObject();
	}

	public final int hashCode() {
	    FixedValue var10000 = this.CGLIB$CALLBACK_0;
	    Object var1 = var10000.loadObject();
            // 此处有类型转换,String类型转换为int类型会抛异常
	    return var1 == null ? 0 : ((Number) var1).intValue();
	}

}

5. CallbackHelper

这种方式可以对不同的方法使用不同的CallBack处理,例如本例中对不是Object类中且方法返回值是String类型(add或delete)的方法用FixedValueInterceptor(返回固定值)处理,其它(比如hashCode)用NoOp(不做任何处理)

@SuppressWarnings("rawtypes")
public class OrderCallbackHelper extends CallbackHelper {

	public OrderCallbackHelper(Class superclass, Class[] interfaces) {
		super(superclass, interfaces);
	}

	@Override
	protected Object getCallback(Method method) {
		if (method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) {
			return new FixedValueInterceptor();
		}
		return NoOp.INSTANCE;
	}

}

 5.1 测试

public static void main(String[] args) {
		
    // System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:/BaiduNetdiskDownload/java-sample");
		
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(OrderService.class);
			
    // 根据不用方法采取不同的处理
    OrderCallbackHelper callbackHelper = new OrderCallbackHelper(OrderService.class, OrderService.class.getInterfaces());
    enhancer.setCallbackFilter(callbackHelper);
    enhancer.setCallbacks(callbackHelper.getCallbacks());
		
    // OrderService$$EnhancerByCGLIB$$47a95d3e
    OrderService orderService = (OrderService) enhancer.create();
    System.out.println(orderService.add("111"));
    System.out.println(orderService.hashCode());
}

输出: 

hello cglib
1343441044

5.2 代理类源码(部分)  


public class OrderService$$EnhancerByCGLIB$$b3f5ea2d extends OrderService implements Factory {
        
        // FixedValueInterceptor实例
        private FixedValue CGLIB$CALLBACK_0;
        // FixedValueInterceptor实例
	private FixedValue CGLIB$CALLBACK_1;
	private NoOp CGLIB$CALLBACK_2;
	private NoOp CGLIB$CALLBACK_3;
	private NoOp CGLIB$CALLBACK_4;
	private NoOp CGLIB$CALLBACK_5;

        // 该方法会被FixedValueInterceptor处理
	public final String add(String var1) {
	    FixedValue var10000 = this.CGLIB$CALLBACK_0;
	    return (String) var10000.loadObject();
	}

        // 该方法会被FixedValueInterceptor处理
	public final String delete(String var1) {
	    FixedValue var10000 = this.CGLIB$CALLBACK_1;
	    return (String) var10000.loadObject();
	}
    
        // 其它方法(例如hashCode,toString)由于会被NoOp处理,又因为NoOp不会做任何处理,所有方法不会被重写

}

6.  LazyLoader

      这种方式用来懒加载一些比较耗资源的对象(new OrderService()),所谓懒加载有两层含义(a.用到时才创建对象,b.只加载一次),本例中,loadObject方法只有在第一次方法(比如add)调用时才调用,第二次调用时不会再调用loadObject方法,会复用上次的返回值

public class OrderLazyLoader implements LazyLoader {

	@Override
	public Object loadObject() throws Exception {
	    System.out.println("cglib load object.");
	    // 对于一些比较耗资源的对象实例化可以在这里使用懒加载
	    OrderService target = new OrderService();
	    return target;
	}
}

6.1 测试

public static void main(String[] args) {
		
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(OrderService.class);
			
    // 自定义LazyLoader
    enhancer.setCallback(new OrderLazyLoader());
		
    // OrderService$$EnhancerByCGLIB$$47a95d3e
    OrderService orderService = (OrderService) enhancer.create();
    System.out.println(orderService.add("111"));
}

 输出:

cglib load object.
add a order[orderNo=111]
success

 6.2 代理类源码(部分)  

public class OrderService$$EnhancerByCGLIB$$b1fa87cb extends OrderService implements Factory {
    
        // OrderLazyLoader实例
        private LazyLoader CGLIB$CALLBACK_0;
        // loadObject()方法返回的实例(OrderService)
        private Object CGLIB$LAZY_LOADER_0;

	public final String add(String var1) {
		return ((OrderService) this.CGLIB$LOAD_PRIVATE_0()).add(var1);
	}

	private final synchronized Object CGLIB$LOAD_PRIVATE_0() {
		Object var10000 = this.CGLIB$LAZY_LOADER_0;
                // 第一次会加载,后面不会再次加载
		if (this.CGLIB$LAZY_LOADER_0 == null) {
			LazyLoader var10001 = this.CGLIB$CALLBACK_0;
			if (this.CGLIB$CALLBACK_0 == null) {
				CGLIB$BIND_CALLBACKS(this);
				var10001 = this.CGLIB$CALLBACK_0;
			}
                        // 获取OrderService实例
			var10000 = this.CGLIB$LAZY_LOADER_0 = var10001.loadObject();
		}
		return var10000;
	}
}

7. Dispatcher

这种方式和LazyLoader类似,只是每次方法调用loadObject方法都会调用一次,其实只是起到了转发的作用,表面上是调用代理类的方法(add/delete),实际上最终的实例对象是由loadObject方法返回的

public class OrderDispatcher implements Dispatcher {

	@Override
	public Object loadObject() throws Exception {
		System.out.println("cglib dispatcher.");
		OrderService target = new OrderService();
		return target;
	}
}

7.1 测试

public static void main(String[] args) {
			
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(OrderService.class);
			
    // 自定义LazyLoader
    enhancer.setCallback(new OrderDispatcher());
		
    // OrderService$$EnhancerByCGLIB$$47a95d3e
    OrderService orderService = (OrderService) enhancer.create();
    System.out.println(orderService.add("111"));
    System.out.println(orderService.delete("222"));
}

输出:

cglib dispatcher.
add a order[orderNo=111]
success
cglib dispatcher.
delete a order[orderNo=222]
success

 7.2 代理类源码(部分)   


public class OrderService$$EnhancerByCGLIB$$c961763b extends OrderService implements Factory {

        // OrderDispatcher实例
	private Dispatcher CGLIB$CALLBACK_0;

	public final String add(String var1) {
		Dispatcher var10000 = this.CGLIB$CALLBACK_0;
		if (this.CGLIB$CALLBACK_0 == null) {
			CGLIB$BIND_CALLBACKS(this);
			var10000 = this.CGLIB$CALLBACK_0;
		}
		return ((OrderService) var10000.loadObject()).add(var1);
	}

	public final String delete(String var1) {
		Dispatcher var10000 = this.CGLIB$CALLBACK_0;
		if (this.CGLIB$CALLBACK_0 == null) {
			CGLIB$BIND_CALLBACKS(this);
			var10000 = this.CGLIB$CALLBACK_0;
		}
		return ((OrderService) var10000.loadObject()).delete(var1);
	}
}

8. ProxyRefDispatcher

Dispatcher类似只是loadObject方法传入了OrderService代理类的实例,暂时还没遇到应用场景

public class OrderProxyRefDispatcher implements ProxyRefDispatcher {

	/**
	 * proxy OrderService$$EnhancerByCGLIB$$9e3fb6d8
	 */
	@Override
	public Object loadObject(Object proxy) throws Exception {
		System.out.println("cglib ProxyRefDispatcher.");
		OrderService target = new OrderService();
		return target;
	}
}

8.1 测试 

public static void main(String[] args) {
		
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(OrderService.class);

    // 自定义ProxyRefDispatcher
    enhancer.setCallback(new OrderProxyRefDispatcher()); 
			
    // OrderService$$EnhancerByCGLIB$$47a95d3e
    OrderService orderService = (OrderService) enhancer.create();
    System.out.println(orderService.add("111"));
    System.out.println(orderService.delete("222"));
}

 输出:

cglib ProxyRefDispatcher.
add a order[orderNo=111]
success
cglib ProxyRefDispatcher.
delete a order[orderNo=222]
success

 8.2 代理类源码(部分)    


public class OrderService$$EnhancerByCGLIB$$9e3fb6d8 extends OrderService implements Factory {

        // OrderProxyRefDispatcher实例
	private ProxyRefDispatcher CGLIB$CALLBACK_0;

	public final String add(String var1) {
		ProxyRefDispatcher var10000 = this.CGLIB$CALLBACK_0;
		if (this.CGLIB$CALLBACK_0 == null) {
			CGLIB$BIND_CALLBACKS(this);
			var10000 = this.CGLIB$CALLBACK_0;
		}
		return ((OrderService) var10000.loadObject(this)).add(var1);
	}

	public final String delete(String var1) {
		ProxyRefDispatcher var10000 = this.CGLIB$CALLBACK_0;
		if (this.CGLIB$CALLBACK_0 == null) {
			CGLIB$BIND_CALLBACKS(this);
			var10000 = this.CGLIB$CALLBACK_0;
		}
		return ((OrderService) var10000.loadObject(this)).delete(var1);
	}

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值