★学习目标:
1、熟悉Spring中两种动态代理方式的区别
2、掌握CGLIB动态代理
★思考任务:
1、什么是CGLib动态代理?
★任务学习:
★知识要点:
如果想代理没有实现接口的类,那么可以使用CGLIB代理。
JDK 动态代理的使用非常简单,但它还有一定的局限性一一使用动态代理的对象必须实现一个或多个接口。如果要对没有实现接口的类进行代理,那么可以使用CGLib代理。CGLib( Code Generation Library )是一个高性能开源的代码生成包,它采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类进行增强。在Spring 的核心包中已经集成了CGLib所需要的包,所以开发中不需要另外导入JAR 包。
接下来,通过一个案例来演示CGLib代理的实现过程,具体步骤如下。
( 1 )在src 目录下,创建一个com . itheima.cglib 包,在包中创建一个目标类UserDao ,UserDao不需要实现任何接口,只需定义一个添加用户的方法和一个删除用户的方法。
//目标类
public class UserDao {
public void addUser() {
System.out.println("添加用户");
}
public void deleteUser() {
System.out.println("删除用户");
}
}
(2 )在com.itheima. cglib 包中,创建代理类CglibProxy ,该代理类需要实现MethodI nterceptor接口,并实现接口中的intercept()方法,
// 代理类
public class CglibProxy implements MethodInterceptor{
// 代理方法
public Object createProxy(Object target) {
// 创建一个动态类对象
Enhancer enhancer = new Enhancer();
// 确定需要增强的类,设置其父类
enhancer.setSuperclass(target.getClass());
// 添加回调函数
enhancer.setCallback(this);
// 返回创建的代理类
return enhancer.create();
}
/**
* proxy CGlib根据指定父类生成的代理对象
* method 拦截的方法
* args 拦截方法的参数数组
* methodProxy 方法的代理对象,用于执行父类的方法
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
// 创建切面类对象
MyAspect myAspect = new MyAspect();
// 前增强
myAspect.check_Permissions();
// 目标方法执行
Object obj = methodProxy.invokeSuper(proxy, args);
// 后增强
myAspect.log();
return obj;
}
}
在代理方法中,首先创建了一个动态类对象Enhancer ,它是CGLib的核心类;然后调用了Enhancer 类的setSuperclass()方法来确定目标对象;接下来调用了setCallback()方法添加回调函数,其中的this 代表的就是代理类CglibProxy 本身;最后通过return 语句将创建的代理类对象返回。intercept()方法会在程序执行目标方法时被调用,方法运行时将会执行切面类中的增强方法。
(3 )在com.itheima.cglib 包中,创建测试类CglibTest。在该类的main()方法中首先创建代理对象和目标对象,然后从代理对象中获得增强后的目标对象,最后调用对象的添加和删除方法,
// 测试类
public class CglibTest {
public static void main(String[] args) {
// 创建代理对象
CglibProxy cglibProxy = new CglibProxy();
// 创建目标对象
UserDao userDao = new UserDao();
// 获取增强后的目标对象
UserDao userDao1 = (UserDao)cglibProxy.createProxy(userDao);
// 执行方法
userDao1.addUser();
userDao1.deleteUser();
}
}
执行程序后,控制台的输出结果

目标类UserDao 中的方法被成功调用并增强了。这种没有实现接口的代理方式,就是CGL旧代理。

