Spring学习第二天Aop_invoke的代理对象生成解析
2018-03-02 20:04
281 查看
我还是事先声明我目前写的都是我的一些理解,仅仅作为我的笔记作为参考!
今天的主要内容就是解析动态代理中的newProxyInstance 和 invoke方法
第一部分:newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h):这个方法主要就是获取代理对象,其实就是委托类的实例,再进一步就是委托类拥有真实业务类的引用,从而这个代理类可以代替真实业务类处理业务逻辑;
ClassLoader:类加载器的作用是什么呢?顾名思义,就是加载类文件,就是.class字节码文件(主要由8位字节码组成),这个部分可以详细的去学习JVM虚拟机;我的通俗理解就是使用这个类加载器对象可以去加载类对象;
Class<?>[]:类,这个类是有一个private的私有构造方法,它是由JVM进行实例化的,大概所有的类都可以作为它的实例,比如User.class,可以是它的一个实例,这个Class的组成呢? 我们通过一些元或者初始化的东西来描述一个类:
包名、类名或者接口、修饰符(类的修饰符、接口的修饰符、属性的修饰符、方法的修饰符)、
方法以及方法参数、成员属性、
注解等等;
InvocationHandler:顾名思义: 调用处理器接口,只有一个invoke的方法;
第二部分:invoke(target,args)方法:
target: 方法名
args: 传入方法名中的参数
综合上面的因素:我们推断: jvm的类加载器加载某一个类(真实业务类),因为加载了这个类所以我们就可以获得这个类的所有的信息(方法、属性啊),然后通过指定方法(这个类中的特定业务逻辑方法)以及参数就可以进行调用了;
其实还是没有理解到代理对象如何执行到业务方法的?然后我想理解的是invoke这个方法的底层:
①
Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
首先我们看下这个方法的实现:在获得代理实例方法里面有下面这个方法:
Class cl = getProxyClass(loader, interfaces);//这个方法主要就是获得代理的真实的类的对象,这个真实的类实现了至少一个接口,这个接口主要是我们自定义的(业务逻辑抽象接口),
/ 加载目标类实现的接口到内存中
interfaceClass = Class.forName(interfaceName, false, loader);
加载相应的接口到内存中,其实也就是加载.class文件中的Class对象到内存中,
// 把目标类实现的接口名称作为缓存(Map)中的key
Object key = Arrays.asList(interfaceNames);
这几个步骤是将第一次生成的Class类中的信息缓存起来,就是存到内存中,下次用的时候直接取,
Map cache;
synchronized (loaderToCache) {
// 从缓存中获取cache
cache = (Map) loaderToCache.get(loader);
if (cache == null) {
// 如果获取不到,则新建地个HashMap实例
cache = new HashMap();
// 把HashMap实例和当前加载器放到缓存中
loaderToCache.put(loader, cache);
}
最关键的是这个一步:
try {
// 中间省略了一些代码 .......
// 这里就是动态生成代理对象的最关键的地方
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
try {
// 根据代理类的字节码生成代理类的实例
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
// add to set of all generated proxy classes, for isProxyClass
proxyClasses.put(proxyClass, null);
}
我们是通过代理生成器来生成代理类的字节码,(注意代理类是含有真实业务的类的引用的),
又当我们获取到一个类的字节码的时候,有一个方法可以直接获取这个类的实例:
defineClass0(loader,proxyName,proxyClassFile,0,proxyClassFile.length);
今天的主要内容就是解析动态代理中的newProxyInstance 和 invoke方法
第一部分:newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h):这个方法主要就是获取代理对象,其实就是委托类的实例,再进一步就是委托类拥有真实业务类的引用,从而这个代理类可以代替真实业务类处理业务逻辑;
ClassLoader:类加载器的作用是什么呢?顾名思义,就是加载类文件,就是.class字节码文件(主要由8位字节码组成),这个部分可以详细的去学习JVM虚拟机;我的通俗理解就是使用这个类加载器对象可以去加载类对象;
Class<?>[]:类,这个类是有一个private的私有构造方法,它是由JVM进行实例化的,大概所有的类都可以作为它的实例,比如User.class,可以是它的一个实例,这个Class的组成呢? 我们通过一些元或者初始化的东西来描述一个类:
包名、类名或者接口、修饰符(类的修饰符、接口的修饰符、属性的修饰符、方法的修饰符)、
方法以及方法参数、成员属性、
注解等等;
InvocationHandler:顾名思义: 调用处理器接口,只有一个invoke的方法;
第二部分:invoke(target,args)方法:
target: 方法名
args: 传入方法名中的参数
综合上面的因素:我们推断: jvm的类加载器加载某一个类(真实业务类),因为加载了这个类所以我们就可以获得这个类的所有的信息(方法、属性啊),然后通过指定方法(这个类中的特定业务逻辑方法)以及参数就可以进行调用了;
其实还是没有理解到代理对象如何执行到业务方法的?然后我想理解的是invoke这个方法的底层:
①
Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
首先我们看下这个方法的实现:在获得代理实例方法里面有下面这个方法:
Class cl = getProxyClass(loader, interfaces);//这个方法主要就是获得代理的真实的类的对象,这个真实的类实现了至少一个接口,这个接口主要是我们自定义的(业务逻辑抽象接口),
/ 加载目标类实现的接口到内存中
interfaceClass = Class.forName(interfaceName, false, loader);
加载相应的接口到内存中,其实也就是加载.class文件中的Class对象到内存中,
// 把目标类实现的接口名称作为缓存(Map)中的key
Object key = Arrays.asList(interfaceNames);
这几个步骤是将第一次生成的Class类中的信息缓存起来,就是存到内存中,下次用的时候直接取,
Map cache;
synchronized (loaderToCache) {
// 从缓存中获取cache
cache = (Map) loaderToCache.get(loader);
if (cache == null) {
// 如果获取不到,则新建地个HashMap实例
cache = new HashMap();
// 把HashMap实例和当前加载器放到缓存中
loaderToCache.put(loader, cache);
}
最关键的是这个一步:
try {
// 中间省略了一些代码 .......
// 这里就是动态生成代理对象的最关键的地方
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
try {
// 根据代理类的字节码生成代理类的实例
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
// add to set of all generated proxy classes, for isProxyClass
proxyClasses.put(proxyClass, null);
}
我们是通过代理生成器来生成代理类的字节码,(注意代理类是含有真实业务的类的引用的),
又当我们获取到一个类的字节码的时候,有一个方法可以直接获取这个类的实例:
defineClass0(loader,proxyName,proxyClassFile,0,proxyClassFile.length);
相关文章推荐
- Spring学习第二天——代理对象,AOP,Spring与JDBC结合,spring要与hibernate版本对应
- Spring AOP 代理对象的生成 part3
- spring学习笔记(7)AOP前夕[2]CGLib动态代理实例解析
- spring生成代理对象的过程(AOP切面)
- Spring AOP源码分析(生成代理对象)
- 深入理解Spring AOP之二代理对象生成
- spring添加<aop:aspectj-autoproxy>让注解自为类生成代理对象时出错
- Spring:AOP(一)生成代理对象
- Spring进阶之路(9)-Spring AOP面向切面编程概念以及通过JDK代理生成AOP代理对象
- 深入理解Spring AOP之二代理对象生成
- Spring进阶之路(10)-Advice简介以及通过cglib生成AOP代理对象
- 重温Spring之旅5——AOP代理对象、JDK动态代理、使用cglib生产代理
- Spring Aop(十三)——ProxyFactoryBean创建代理对象
- Spring AOP 学习之cJlib动态代理
- Spring学习笔记:使用代理实现AOP
- CgLib动态代理学习【Spring AOP基础之一】
- Spring4学习笔记-AOP前传之动态代理
- Aop源码分析之生成代理对象
- [Spring学习笔记 4 ] AOP 概念原理以及java动态代理