CJLIB动态代理代码实现
被代理类
public class CameraSuoni {
public void photo(){
System.out.println("用索尼相机给美女照了一张相");
}
}
代理对象和代理处理器类
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CaremaCGLIBProxy implements MethodInterceptor{
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class cla){
//创建被代理类的子类字节码
enhancer.setSuperclass(cla);
//回调,回调intercept方法
enhancer.setCallback(this);
//根据字节码技术创建被代理类子类实例
Object obj = enhancer.create();
return obj;
}
public Object intercept(Object obj, Method method, Object[] arg2,
MethodProxy arg3) throws Throwable {
System.out.println("cglib动态代理----------------照相自带ps美白功能");
arg3.invokeSuper(obj, arg2);
return null;
}
}
测试类
public class CaremaCGLIBTest {
public static void main(String[] args){
//被代理对象
CameraSuoni camera = new CameraSuoni();
//代理处理器和代理对象创建类
CaremaCGLIBProxy proxy = new CaremaCGLIBProxy();
//代理对象
camera = (CameraSuoni) proxy.getProxy(camera.getClass());
//已经带有其他效果的代理对象方法
camera.photo();
}
}
输出结果
cglib动态代理----------------照相自带ps美白功能
用索尼相机给美女照了一张相
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。
这里看一下CGLIB和JDK实现的原理其实很像的,CaremaCGLIBProxy实现了MethodInterceptor,CaremaCGLIBProxy中的intercept方法和实现InvocationHandler的类中的invoke方法很相似,都是通过反射执行被代理对象的原方法。CaremaCGLIBProxy中的getProxy方法和Proxy的newInstatceProxy方法功能也是一样的,都是创建代理对象。
CGLIB动态代理的原理
CGLIB动态代理就是将被代理对象和增强对象组合在一起生存一个代理对象的字节码文件,再然后通过这个字节码文件生成代理对象,代理对象将被代理对象作为父类进行继承,在代理对象中重写了父类的方法。我们在调用代理对象的方法时候,就会实现增强和父类方法中所实现的效果。
CGLIB动态代理和JDK动态代理的不同和相同点
相同点
CGLIB和JDK都是通过字节码文件生成代理实例,不需要创建代理对象源文件。
两者的具体实现方式也是很相似的,JDK代理有一个代理处理器实现了InvokeHandler接口,重写invoke方法,在invoke方法中通过反射调用目标对象的方法。
GLIB代理是有一个方法拦截处理器实现了MethodInterceptor,重写intercept方法,在intercept方法中利用反射调用目标对象的方法。
JDK代理是通过Proxy来生成代理对象,CLIB代理是通过Enhancer来生成动态代理对象
不通点
JDK中的被代理对象必须实现接口,代理对象和被代理对象实现的是同一个接口
CGLIB被代理对象可以不实现接口,代理对象继承了被代理对象,所以CGLIB中的被代理对象不能有final修饰,代理对象调用的方法在被代理对象中也不能是fianl