关键词:Spring | AOP | 创建代理类 | 底层
本专栏通过理论和实践相结合,系统学习框架核心思想及简单原理,原创不易,如果觉得文章对你有帮助,点赞收藏支持博主 ✨
public static void main(String[] args) {
//1. 创建原始对象
UserService userService = new UserServiceImpl();
//2. 创建动态代理,使用JDK
Proxy.newProxyInstance(loader, interfaces, InvocationHandler);
}
JDK的动态代理是实现的第三个参数, InvocationHandler
接口中的 invoke()
UserService userService = new UserServiceImpl();
/**
* 作用:用于编写额外功能,可以运行在原始方法前,后,前后,异常等情况
* @param proxy 表示代理对象,可以忽略
* @param method 额外功能加给哪个原始方法
* @param args 原始方法参数
* @return 原始方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//额外功能
//反射调用,更灵活
Object invoke = method.invoke(userService, args);
return invoke;
}
接口实现和之前学习的 MethodInterceptor
很像,其实方法拦截器就是由这个方法封装过的
第二个参数是 Class>[] interfaces
,原始对象所实现的接口,只有拿到相同的接口,才能根据接口进一步代理
UserService.getClass().getInterfaces()
第一个参数是 ClassLoader loader
,又叫类加载器,主要作用有两个:
如何获得类加载器?
每一个类的.class
文件,都会被自动分配与之对应的类加载器(Class Loader)
但是动态代理类使用了动态字节码技术来创建字节码,没有源文件和字节码文件,直接将字节码写入虚拟机,没有加载的字节码的过程,那我们要获得代理对象,前面拿到原始类对象的字节码文件后,可以创建代理类对象了吗?
不可以,因为想要创建代理类对象,必须先获得代理类 Class 对象,就需要类加载器的帮助,但是动态代理没有 .clsss
文件,也就没有与之分配的类加载器
但是此时需要类加载器,怎么办?借一个,完成代理类 Class 对象的创建,进而完成代理类对象的创建
TestJDKProxy
public class TestJDKProxy {
public static void main(String[] args) {
//1. 创建原始对象
UserService userService = new UserServiceImpl();
//2. 创建动态代理,使用JDK
InvocationHandler handler = (proxy, method, args1) -> {
System.out.println("--------Proxy log4--------");
// 执行方法
Object reg = method.invoke(userService, args1);
return reg;
};
UserService useServiceProxy = (UserService) Proxy.newProxyInstance(TestJDKProxy.class.getClassLoader(), userService.getClass().getInterfaces(), handler);
useServiceProxy.login("哈哈", "123");
}
}
Result
--------Proxy log4--------
UserServiceImpl login + DAO
没有任何问题
Cglib是通过父子继承关系创建代理对象,原始类作为父类,代理类作为子类,这样既可以保证既可以保证方法一致的情况下,在代理类中提供新的实现(原始方法 + 额外功能)
TestCglib
public class TestCglib {
public static void main(String[] args) {
//1.创建原始对象 UserService
UserService userService = new UserService();
//2.通过Cglib创建动态代理对象
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(TestCglib.class.getClassLoader());
enhancer.setSuperclass(userService.getClass());
MethodInterceptor methodInterceptor = new MethodInterceptor(){
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("---Cglib log---");
Object ret = method.invoke(userService, objects);
return ret;
}
};
enhancer.setCallback(methodInterceptor);
UserService userServiceProxy = (UserService) enhancer.create();
userServiceProxy.login("哈哈", "12312312");
}
}
Result
---Cglib log---
核心功能,登录操作
JDK: 通过接口创建代理类对象
Cglib: 通过继承创建代理类对象
有接口使用 JDK
,没有就是用 Cglib
座右铭:不要在乎别人如何看你,要在乎你自己如何看未来,看梦想,看世界…!
一起学习的可以私信博主或添加博主微信哦。
专栏:订阅专栏 ✅
关注:关注博主