上一篇我们介绍了JDK动态代理,回顾一下,它主要是通过代理类实现InvocationHandler接口,Proxy类调用newProxyInstance()方法来实现的。今天要说的cglib动态代理其实和JDK动态代理很相似。
一、jar包的获取
首先,提供2种cglib使用的包:- 通过Maven仓库下载cglib的jar包,目前最高版本是3.3.0
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
- Spring框架中已经集成了cglib的jar包,只要有Spring的核心包就可以使用cglib,同样也可以使用Maven来下载,这是我用的:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.13.RELEASE</version>
</dependency>
二、举个栗子
然后,我们来看一个简单的例子:(1)接口类:
public interface Subject {
public void request();
}
(2)被代理类:
public class RealSubject implements Subject{
public RealSubject() {
}
@Override
public void request() {
System.out.println("我是工程师,哈哈!");
}
}
(3)为了让逻辑关系更清楚,我单独分离了一个切面类:
public class MyAspect {
public void After() {
System.out.println("After前台。。。");
}
public void Before() {
System.out.println("Before前台。。。");
}
}
(4)代理类的调用子程序:
从理解的角度说,和JDK动态代理相似,这个代理的调用类实现了MethodInterceptor接口,并重写了intercept()方法,它的目的是创建拦截器,和InvocationHandler接口相似
public class ProxySubject implements MethodInterceptor{
private Object object;
MyAspect myAspect = new MyAspect();
public ProxySubject(Object obj) {
object=obj;
}
@Override
public Object intercept(Object proxy, Method method, Object[] arg2, MethodProxy methodProxy) throws Throwable {
myAspect.Before();
Object obj=method.invoke(object, arg2);
myAspect.After();
return obj;
}
}
在intercept()方法中有4个参数:
- proxy表示代理对象
- method表示目标类中的方法
- args2表示方法参数(invoke()方法中的第二个参数)
- methodProxy表示代理方法的MethodProxy对象
(5)核心的cglib类:
public class ProxyFactory {
public static RealSubject getBean() {
//目标类
RealSubject realSubject = new RealSubject();
ProxySubject ps = new ProxySubject(realSubject);
Class<?> cl = realSubject.getClass();//获取反射对象
Enhancer enhancer = new Enhancer();//增强器对象
enhancer.setSuperclass(cl);//设置目标类的字节码文件
enhancer.setCallback(ps);//设置回调对象
RealSubject prs= (RealSubject) enhancer.create();//创建代理对象
return prs;
}
}
(6)测试类:
public class TestClient {
@Test
public void test() {
RealSubject rs=ProxyFactory.getBean();
rs.request();//通过代理类调用方法
}
}
(7)最后,运行结果是这样的:
三、JDK 与 cglib的 区别
好了,大概就是这个丫子,貌似和jdk动态代理很相似,但它们的核心实现方式是不一样的- JDK动态代理使用JDK中集成的代理功能,无需其他依赖,而cglib则需要单独下载jar包导入依赖
- JDK动态代理是对实现接口类的对象创建代理,无法对象没有实现接口的类创建代理,而cglib代理恰恰弥补了JDK代理的缺点,采用ASM字节码生成框架,通过字节码底层继承要代理类来实现
没有做源码层面的解释,留给你去探索啦*⸜(•ᴗ•)⸝*