4.2 ClassLoder
JVM在运行时会产生三个ClassLoder:
- 根装载器
- 根装载器不是Class的子类,是用C++编写的
- 根装载器负责JRE的核心类库,如JRE目录下的
- ExtClassLoder(扩展类装载器)
- AppClassLoder(应用类装载器)
这三个装载器之间是存在父子层级关系的,根装载器是ExtClassLoder的父装载器,而ExtClassLoder是AppClassLoder的父装载器。并且Java允许编写自己的ClassLoder
JVM中的Class对象
- 每个类在JVM中都存在自己的java.lang.Class对象,它提供了类型结构信息的描述
- 数组,注解,枚举和基本类型甚至void都存在自己的java.lang.Class对象
- Class 没有public构造方法,Class 是JVM通过调用ClassLoder中的defineClass方法进行构造的
新发现:
- 为什么实现RPC远程调用必须序列化,以下是个人猜想
- 因为在ClassLoder中存在一个方法:defineClass 这个方法的主要作用就是将一个字节数组转换成JVM内部的java.lang.Class对象,字节数组可以从本地文件系统,远程网络获取,参数name为字节数组对应的全限定类名
- 从上面的解释可以看出我们可以通过远程获取序列化对象,并且通过defineClass方法转换额为JVM内部的Class文件,同时也可以这样理解,defineClass方法实现了Class文件的反序列化
提问区:
- 什么是全盘负责委托机制
4.2.3 Java反射机制
- Constructor: 类的构造函数反射类,可以通过Class类的getConstructors()可以获取当前类的所有构造方法
- Method: 方法的反射类,可以通过getDeclaredMethods()方法获取所有方法反射类对象数组Method[]
-
4.4.2 ApplicationContext 介绍
ApplicationContext 继承了BeanFactory,通过xml方式加载的实现类主要有两个:
- ClassPathXmlApplicationContext : 从类路径加载配置文件,默认会在resource文件夹下寻找
- FileSystemXmlApplicationContext :通过绝对路径加载配置文件
并且ApplicationContext与BeanFactory最大的不同在于BeanFactory使用的是延迟加载的方式进行Bean的加载,而ApplicationContext则是会在初始化容器时加载所有非延迟加载的单例的Bean,并放入容器中,也就是说ApplicationContext是非延迟加载的。
这里需要注意一点:只有单例的bean才会有延迟加载和非延迟加载的概念,如果是多例,因为每次都是重新创建一个新的对象所以不存在这两种概念
Spring 也为ApplicationContext提供了注解的一种实现类AnnotationConfigApplicationContext,可以通过以下方式获取类的实例:
在通常情况下Spring只存在两种作用域,单例作用域和多例作用域,但是在Spring中存在一个转为Web准备的ApplicationContext,也就是WebApplicationContext,在WebApplicationContext中新增了三个作用域:
- request
- session
- global session
并且WebApplicationContext的初始化需要ServletContext的实例,同时我们还可以自定义作用域,说明如下所示:
Spring的单例作用域
由于数据访问层一定会持有Connection这个对象,但是该对象是非线程安全的, 因此为了防止多线程导致的单例问题,数据访问层往往采用的是非单例的对象,但是在Spring利用AOP和ThreadLocal对非线程安全的变量进行了,使这些非线程安全的类变成线程安全的类。
在其被他类引用的情况下,延迟加载会被忽略,直接装载入容器
Spring 的原型(Prototype)作用域
Spring的原型作用域是指非单例的作用域,当Spring将Bean交给调用者后将不再管理Bean 的生命周期,并且在使用完成后用会在gc时被垃圾回收掉。