Spring Bean Class 加载阶段
上一节分析了关于 BeanDefinition 合并的细节过程, 那么接下来在 Spring Bean 被创建之前, 需要将Bean对应的class进行加载. 那么这里就要涉及到一些细节需要理清.
ClassLoader 类加载
第一个涉及到 java 里面的一些基础, ClassLoader , 这个东西其实接触框架的同学会更加熟悉, java的类加载主要是依靠 ClassLoader 来进行的.
可以参考:
java ClassLoader详解
Java Security 安全控制
第二个是关于java security,就是Java安全里面的一些控制,在spring早期是没有增加这块的实现的,后期开始增加了一些相关的控制,多提一点,过去是spring在实现的时候,在 IoC 的实现DI和我们说依赖注入和依赖查找的时候,他没有注重关于Java Security的一个安全整合,不过在这方面 Java EE 规范里面有清晰的描述,所以后续在当前版本看的时候,会发现里面有一些 Java Security API 的代码,后面会讲到这些代码的作用.
ConfigurableBeanFactory 临时ClassLoader
第三个方面,这个方面是个大的方面,这个方面本节其实选择性的跳过,后面会带入一个简单的场景和大家分析一下,这个场景实际上是非常有限的,通常我们是用不到的。
代码示例
java.lang.ClassLoader
org.springframework.beans.factory.config.BeanDefinition
org.springframework.beans.factory.support.AbstractBeanFactory
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
org.springframework.util.ClassUtils
java.lang.Class
org.geekbang.thinking.in.spring.bean.lifecycle.MergedBeanDefinitionDemo
从问题开始, BeanDefinition 是怎么 从文本的元信息形式加载到 Class 的?
好,我们还是回到idea里面来,前面章节知道了 BeanDefinition 在合并之后会生成 RootBeanDefinition。那么接下来有很重要的一个操作,就是我们前面看到过 BeanDefinition 实际上里面有一个很重要的信息,这个是我们的bean的一个基本的来源,也就是说它会 getBeanClassName 。
org.springframework.beans.factory.config.BeanDefinition#getBeanClassName
/**
* Return the current bean class name of this bean definition.
* <p>Note that this does not have to be the actual class name used at runtime, in
* case of a child definition overriding/inheriting the class name from its parent.
* Also, this may just be the class that a factory method is called on, or it may
* even be empty in case of a factory bean reference that a method is called on.
* Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
* rather only use it for parsing purposes at the individual bean definition level.
* @see #getParentName()
* @see #getFactoryBeanName()
* @see #getFactoryMethodName()
*/
@Nullable
String getBeanClassName();
前面我们也分析过,其实 BeanDefinition 它是一个关于Bean的元信息的配置或者是描述,那么事实上它是通过文本的方式来进行呈现的,它这里并没有显式的告诉你它的类是什么,我们知道Java里面类的描述是通过Class来进行表达,那么Class又是由 ClassLoader 来进行加载的,因此这个BeanDefinition 实例化这一过程和我们的传统的Java的作用机制肯定是跑不掉的。
java.lang.ClassLoader
/**
* A class loader is an object that is responsible for loading classes. The
* class <tt>ClassLoader</tt> is an abstract class. Given the <a
* href="#name">binary name</a> of a class, a class loader should attempt to
* locate or generate data that constitutes a definition for the class. A
* typical strategy is to transform the name into a file name and then read a
* "class file" of that name from a file system.
*
*/
public abstract class ClassLoader {
事实上在 Spring IoC容器的实现里面,ClassLoader 加载是一个边缘化的操作(其实是封装的太深了…),通常我们不太重视,接下来我们会通过一个方法的方式来进行操作。
首先我们看回之前的示例 MergedBeanDefinitionDemo,然后在依赖查找的位置打上断点:
org.geekbang.thinking.in.spring.bean.lifecycle.MergedBeanDefinitionDemo
org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(java.lang.String, org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.config.BeanDefinition)