Spring Bean加载流程分析(通过 XML 方式加载)( 二 )

通过该构造方法 , 我们可以知道该构造方法初始了一个类加载器 。 如果类加载器不为空 , 则复制成默认的类加载器 。 如果类加载器为空 , 则通过 ClassUtils.getDefaultClassLoader() 方法获取一个默认的类加载器 。 而我们传入的类加载器显然为 null , 则 Spring 会去自动获取默认的类加载器 。
public static ClassLoader getDefaultClassLoader() {ClassLoader cl = null;try {//1.获取当前线程的类加载器cl = Thread.currentThread().getContextClassLoader();}catch (Throwable ex) {// Cannot access thread context ClassLoader - falling back...}if (cl == null) {// No thread context class loader -> use class loader of this class.// 2. 获取当前类的类加载器cl = ClassUtils.class.getClassLoader();if (cl == null) {// getClassLoader() returning null indicates the bootstrap ClassLoadertry {//获取系统级的类加载器/应用类加载器 AppClassLoadercl = ClassLoader.getSystemClassLoader();}catch (Throwable ex) {// Cannot access system ClassLoader - oh well, maybe the caller can live with null...}}}return cl;}复制代码通过 getDefaultClassLoader 方法我们可以知道 , Spring 在获取类加载器做了如下三件事:

  • 获取当前线程的类加载器 , 如果存在 , 则返回 。 不存在则往下执行
  • 获取加载当前类的类加载器 , 如果存在 , 则返回 。 不存在则往下执行
  • 如果以上两步均没有获取到类加载器 , 则获取系统级类加载器/应用类加载器 。
这里很好的利用了一个回退机制 , 用一个通俗的话语来解释回退机制就是退而求其次 。 先获取最合适的 xxx 。 如果获取不到 , 再获取其次合适的 xx 。 如果还是获取不到 , 就再退一步获取 x 。
2. 初始化 BeanFactory接下来我们看示例代码中的第二行代码的实现
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();复制代码看看 new DefaultListableBeanFactory() 方法做了什么?
/** * 创建一个默认的 BeanFactory * Create a new DefaultListableBeanFactory. */public DefaultListableBeanFactory() {super();}复制代码一个空的实现 , 但是调用了父类的构造方法 , 跟进一步 , 看看父类的构造方法做了什么事情 。
public AbstractAutowireCapableBeanFactory() {super();ignoreDependencyInterface(BeanNameAware.class);ignoreDependencyInterface(BeanFactoryAware.class);ignoreDependencyInterface(BeanClassLoaderAware.class);}复制代码同样 , 该构造方法也调用了父类的构造方法 , 跟进父类的构造方法一探究竟 。
public AbstractBeanFactory() {}复制代码空实现 , 没啥好看的 。 看看 AbstractAutowireCapableBeanFactory 里面的另外三个方法 。 通过方法的名称我们可以大致猜出 , 这是为了忽略某些特定的依赖接口 。
private final Set> ignoredDependencyInterfaces = new HashSet<>();public void ignoreDependencyInterface(Class ifc) {this.ignoredDependencyInterfaces.add(ifc);}复制代码没有太多的复杂逻辑 , 只是将某些特定的 class 对象放进了一个 set 集合中 , 标记这些接口应该被忽略 , 或许这个 set 集合会在后面的某一处使用到 。 但是注意 , 只有 BeanFactory 的接口应该被忽略 。
3. 定义 BeanDefinitionReader 对象接下来我们看第三行代码的实现
BeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);复制代码


推荐阅读