简单介绍:
在之前我们使用JDK动态代理的方式实现了增强方法,但是这个有一个小小的缺陷,就是他只能实现接口中的增强方法。 什么意思呢,就是说她的所有的增强都是对于接口而言的,注意到我们之前无论是获取代理对象还是获取动态代理之后的对象,都是通过接口类而不是实现类 也就是说接口在这里起到了一个非常关键的作用,就是连接被代理对象和代理对象,他们通过同一个接口来确定属于同一个对象。 但是有一个问题,就是如果我们的类并没有实现任何的接口的时候,我们要如何创建一个类的代理对象呢? 这时候我们就需要一个新的动态代理方式,叫做CGLib动态代理。
使用方法:
这个类的核心就是要通过一个类去实现MethodInterceptor接口,并实现接口中的intercept()方法对动态代理类的方法进行增强,并且使用Enhancer来创建动态代理对象。只要理解了之前JDK的动态代理方式,CGLib的动态代理和之前的JDK动态代理的区别主要在于获取的是类的对象而不是接口的对象。
大致的原理就是我们通过传入被代理对象的类,以及我们的回调函数,回调函数的参数就是我们的本类,this关键字 然后就可以使用Enhancer的create()方法获取到动态代理之后的对象 intercept()方法还是跟之前一样,主要用于处理我们的增强方法和原始方法之间的关系 只不过我们调用的是invokeSuper()方法,参数就是被代理对象和方法的参数 就表示将拦截我们所有的对原始方法的调用,而改为调用我们动态代理的之后的类的增强之后的方法
对于在什么时候时使用JDK动态代理什么时候使用CGLib动态代理,主要看我们的被代理对象 是实现接口中的的方法还是继承自父类的方法,JDK主要用于动态代理接口中的方法,CGLib主要用于 动态代理来自于继承的方法.
对于这个地方,如果实在不能理解其实也无所谓,这是AOP的底层实现,对于Spring的AOP,我们主要 是使用XML配置文件和注解的方式去使用他帮我们封装后的,使用更简单的面向切面的编程.
在我们之后的面向切面的编程中,无论是基于XML配置文件的,还是基于注解的编程 我们都只需要记住一句话即可:插什么?插谁?插在什么位置 只需要明确这三个问题,之后的就是使用标签或者注解去完成配置即可。
代码实现:
在了解了理论之后,我们来通过代码的方式去将理论实现:
首先,我们还是首先需要一个原始的类或者说需要增强的类:
package Semester_4.AOP.CGLibDynamicProxy;
public class UserDAO {
public void addUser(){
System.out.println("添加用户");
}
public void deleteUser(){
System.out.println("删除用户");
}
}
然后是我们的切面类,也就是存放了增强方法的类:
package Semester_4.AOP.CGLibDynamicProxy;
public class EnhancedMethods {
public void chinkPermissions(){
System.out.println("模拟检查权限的过程……");
}
public void log(){
System.out.println("模拟写日志的过程……");
}
}
然后就是创建一个类,去实现MethodInterceptor接口,在这个类中,我们需要完成创建动态代理类和处理增强方法和原方法的关系:
package Semester_4.AOP.CGLibDynamicProxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 这个方法是用来创建动态代理类对象的
*
*/
public class DynamicProxy implements MethodInterceptor {
public Object createProxy(Object ud){
// 其中Enhancer类是用来将被代理对象经过包装之后返回被代理类的对象的
Enhancer e = new Enhancer();
// 获取被代理对象的类
e.setSuperclass(ud.getClass());
// 然后获取回调函数,这个回调函数就是用来执行被增强后的方法的类
e.setCallback(this);
// 最后返回动态代理之后的方法
return e.create();
}
/**
*
* @param o 表示根据类指定生成的
* @param method 表示要拦截的方法
* @param objects 表示方法的参数
* @param methodProxy 方法的代理对象,用于执行父类的方法,也就是增强之前的方法
* @return 返回的是经过动态代理之后的对象
* @throws Throwable 抛出一个异常
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// 获取增强类的对象,用来调用增强的方法
EnhancedMethods em = new EnhancedMethods();
em.chinkPermissions();
// 这里是调用invokeSuper(被代理的类,被代理的类的方法的参数)
// 表示将调用普通类的方法,保证增强之前的方法能正常的执行
Object invoke = methodProxy.invokeSuper(o, objects);
em.log();
// 最后返回代理之后的对象
return invoke;
}
}
主要的就是使用Enhancer类去获取动态代理对象,并且通过intercept()方法去处理增强方法与原始方法的关系,完成配置之后,我们就可以来到测试类进行测试了:
package Semester_4.AOP.CGLibDynamicProxy;
public class test {
public static void main(String[] args) {
// 首先我们创建被代理类的对象,这里我们就是创建本类的对象
UserDAO ud = new UserDAO();
// 然后创建我们之前编写的动态代理类创建对象
DynamicProxy dp = new DynamicProxy();
// 然后我们将被代理的对象转换成动态代理之后的对象
UserDAO ud2 = (UserDAO) dp.createProxy(ud);
// 通过动态代理之后的对象调用方法
ud2.addUser();
ud2.deleteUser();
}
}
运行结果:
跟之前的运行结果是一样的,虽然结果是一样的,但是我们自己要知道,两种方法的实现原理是不一样的。并且要知道这两种方法的区别。
注意点:
在使用CGLib的动态代理方法的时候,首先我们要创建一个原始类,然后创建切面,最后我们要创建一个类去实现MethodInterceptor接口,这个类用来创建动态代理对象,并且处理原始方法与增强方法之间的关系。
还有一点,对于这个地方,如果实在不能理解其实也无所谓,这是AOP的底层实现,对于Spring的AOP,我们主要 是使用XML配置文件和注解的方式去使用他帮我们封装后的,使用更简单的面向切面的编程。在我们之后的面向切面的编程中,无论是基于XML配置文件的,还是基于注解的编程 我们都只需要记住一句话即可:插什么?插谁?插在什么位置 只需要明确这三个问题,之后的就是使用标签或者注解去完成配置即可。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/153286.html