CGlib动态代理

CGlib所需jar包:
asm-7.0.jar和cglib-3.2.10.jar
通过一个计算器的实现来简单描述CGlib动态代理的作用和原理。

public class Calculator {

	public int add(int a, int b) {
		int result = a+b;
		return result;
	}	
}

然而,如果想要在add方法执行时添加一些日志信息,我们就必须在实现类中增加代码量,例如:

public class Calculator{

	public int add(int a, int b) {
		System.out.println(this.getClass().getName()+":The add method begins.");
		System.out.println(this.getClass().getName()+":Parameters of the add method: ["+a+","+b+"]");
		int result = a+b;
		System.out.println(this.getClass().getName()+":Result of the add method:"+result);
		System.out.println(this.getClass().getName()+":The add method ends.");
		return result;
	}
}

并且如果想要添加减法,乘法,除法等功能以及对应的日志信息则实现类中的代码量会非常之多,其中很多代码都是重复的,因此我们利用CGlib动态代理来完成代码复用:

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ProxyFactory {
	static Calculator target;
	static Callback callback = new MethodInterceptor() {
		
		@Override
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			String name = method.getName();
			System.out.println(this.getClass().getName()+":The "+name+" method begins.");
			System.out.println(this.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]");
			Object result =method.invoke(target, args);
			//根据calculatorProxy.add(1, 2);的add方法名来找到Calculator中的method对象,也就是说在此完成对目标方法的调用
			System.out.println(this.getClass().getName()+":Result of the "+name+" method:"+result);
			System.out.println(this.getClass().getName()+":The "+name+" method ends.");
			return result;
		}
	};
	public static Object getProxy(Calculator target) {
		ProxyFactory.target = target;	
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(target.getClass());//产生谁的代理对象
		enhancer.setCallback(callback);//要做什么	
		return enhancer.create();//返回代理对象
	}
}

上面代码为目标对象创建代理对象,我们执行测试代码:

package com.zzu.test;

import com.zzu.calculator.Calculator;
import com.zzu.calculator.ProxyFactory;

import net.sf.cglib.core.DebuggingClassWriter;

public class Test {

	public static void main(String[] args) {
		Calculator calculator = (Calculator) new ProxyFactory().getProxy(new Calculator());//获取代理对象
		int a = calculator.add(1, 2);
		System.out.println(a);
	}
}

执行结果:

com.zzu.calculator.ProxyFactory$1:The add method begins.
com.zzu.calculator.ProxyFactory$1:Parameters of the add method: [1,2]
com.zzu.calculator.ProxyFactory$1:Result of the add method:3
com.zzu.calculator.ProxyFactory$1:The add method ends.
3

CGlib动态代理与JDK动态代理的区别就是,JDK动态代理实现了被代理类所实现的接口,相当于兄弟关系,而CGlib动态代理是继承自被代理对象。下面我们证明继承关系。
在Test类中添加代码:

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");

生成使用CGlib创建动态代理对象的class文件,注意该代码写在代理对象创建之前。
执行测试类之后生成文件Calculator$$EnhancerByCGLIB$$5817bedc.class,在eclipse中打开:
在这里插入图片描述
代理对象继承自被代理对象。
CGLib动态代理
程序执行时通过ASM(开源的Java字节码编辑库,操作字节码)jar包动态地为被代理类生成一个代理子类,通过该代理子类创建代理对象,由于存在继承关系,所以父类不能使用final修饰。

JDK动态代理与CGLib动态代理区别:
1、JDK动态代理基于接口实现,所以实现JDK动态代理,必须先定义接口;CGLib动态代理基于类实现;
2、JDK动态代理机制是委托机制,委托hanlder调用原始实现类方法;CGLib则使用继承机制,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。

动态代理优点:
1、静态代理在程序执行前需手动创建代理类,如果需要很多代理类,每一个都手动创建不仅浪费时间,而且可能产生大量重复性代码,此时我们就可以采用动态代理。
2、动态代理通过InvocationHandler接口invoke方法或MethodInterceptor接口intercept方法为被代理对象中的方法增加额外功能,这种方式比静态代理中通过代理类逐一为被代理对象中的方法增加额外功能,更加的灵活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CGLIB是一个强大的开源代码生成库,它可以在运行时扩展Java实现接口CGLIB动态代理CGLIB库的一个重要特性,它通过生成目标的子实现代理。 在CGLIB动态代理中,我们可以使用`MethodInterceptor`接口来定义代理逻辑。`MethodInterceptor`接口有一个`intercept`方法,该方法在目标方法被调用时被触发。在`intercept`方法中,我们可以编写自定义的逻辑来增强目标方法的功能。 下面是一个使用CGLIB动态代理的示例代码: ```java import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibProxyExample implements MethodInterceptor { public Object createProxy(Object target) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 在目标方法执行前的逻辑 System.out.println("Before method: " + method.getName()); // 调用目标方法 Object result = proxy.invokeSuper(obj, args); // 在目标方法执行后的逻辑 System.out.println("After method: " + method.getName()); return result; } } ``` 在上述示例中,我们首先创建了一个`CglibProxyExample`实现了`MethodInterceptor`接口。然后,我们通过`Enhancer`创建了一个代理对象,并设置了目标和代理逻辑。在`intercept`方法中,我们可以在目标方法执行前后添加自定义的逻辑。 使用CGLIB动态代理时,我们可以通过调用`createProxy`方法来创建代理对象。例如: ```java SomeClass target = new SomeClass(); CglibProxyExample proxyExample = new CglibProxyExample(); SomeClass proxy = (SomeClass) proxyExample.createProxy(target); ``` 这样,我们就可以通过`proxy`对象来调用目标的方法,并在方法执行前后添加自定义的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值