spring的bean加载

2024-06-24 08:18
文章标签 java 加载 spring bean

本文主要是介绍spring的bean加载,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们经常使用Spring,并且也都了解其大概原理。我想我们一定会对Spring源码的解读有迫切的渴望。
我也如此。所以,我打算阅读一下Spring的源码。再此之前,我也为此准备了很多。包括,去复习熟练java反射,理解常用的设计模式。当然,这些复习笔记也会在今后的复习中顺便记录在我的csdn博客。(当然,可能写的不好,也可能理解不正确(可以一起交流嘛)。但是乐于分享总归是好的。)

首先看下spring的各个组件。


可以看到,在Core Container(核心容器)中包含有Core、Beans、Context和Spring Expression Language.Core和Beans模块是Spring框架的基础部分,提供IoC控制反转和依赖注入的特性。
Core模块主要包含着Spring框架基本的核心工具类,供其它组件使用。
Beans模块是所有应用都要用到的,它包含访问配置文件、创建和管理bean以及ioc、依赖注入。
Context模块构建于Core和Beans之上。是spring的上下文环境,为Spring核心提供了大量的扩展,天津挨了对国际化、事件传播、资源加载等支持。ApplicationContext接口是Context模块的关键。
Spring Expression Language为Spring提供了一个强大的表达式语言用于在运行时查询草操纵对象 。

现在我们已经了解了Spring的基础组件,我们现在就在代码中跟踪一下Spring Bean的创建和获取过程。
beans.xml
<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">  <bean id="hello" class="bean.HelloSpring" lazy-init="false"></bean>  </beans>  

HelloSpring.java
package bean;  /** * Created by yuyufeng on 2016/11/17. */  
public class HelloSpring {  private String name;  public HelloSpring() {  System.out.println("##HelloSpring.HelloSpring初始化……………………………………");  }  public HelloSpring(String name) {  this.name = name;  }  public void sayHello(String something){  System.out.println("hello"+something);  }  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  @Override  public String toString() {  return "HelloSpring{" +  "name='" + name + '\'' +  '}';  }  
}  

BeanFactoryTest.java
package spring.ioc;  import bean.HelloSpring;  
import org.springframework.beans.factory.BeanFactory;  
import org.springframework.beans.factory.xml.XmlBeanFactory;  
import org.springframework.core.io.ClassPathResource;  
import org.springframework.core.io.Resource;  /** * Created by yuyufeng on 2016/11/18. * Spring中Bean的加载过程 */  
public class BeanFactoryTest {  public static void main(String[] args) {  //spring如何初始化有两种方式 beanFactory applicationContext  Resource resource = new ClassPathResource("spring/ioc/beans.xml");  BeanFactory beanFactory = new XmlBeanFactory(resource);  HelloSpring helloSpring = (HelloSpring) beanFactory.getBean("hello");  helloSpring.sayHello("张三");  }  
}  

先从表面上可以看到 bean的加载可大致可以分为:从xml读取bean的信息加载到Spring容器中,通过xml配置的id从Spring容器反射得到这个类的实例对象。
现在,我们进行详细分析
1.Resource resource = new ClassPathResource("spring/ioc/beans.xml");
我们通过Sring Core模块的工具从本地获得了xml资源,并生成Resource对象。这一过程就不详细跟进了。
2.通过XmlBeanFactory来创建BeanFactory对象。
直接debug进入


3.首先我们会跟进 DefaultSingletonBeanRegistry 其中有静态对象需要实例化。至于为什么会跟进这个类,我们来看下类的继承关系就知道了(为什么会先实例其中的静态类,可以复习以下java对象的实例顺序)


4.接着会进入DefaultListableBeanFactory创建里面的静态对象实例以及执行里面的静态模块



5.通过类加载器注入DefaultListableBeanFactory对象
然后又实例化了一个存放DefaultListableBeanFactory的map


6.接着再执行XmlBeanFactory的构造方法,其中把配置文件Resource赋值给了resource


7.执行this.reader.loadBeanDefinitions(resource); //可以看到这个步骤是要把resource加载到容器中去了。这里是整个资源加载进入的切入点。

8.接着再跟进,直到进入public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException ;方法


9.对导入资源再进行一定包装处理后进入doLoadBeanDefinitions(inputSource, encodedResource.getResource()); //对于encode我们是比较熟悉的 肯定是处理编码相关的


10.现在已经进入到了XmlBeanDefinitionReader.java,
再包装处理(毕竟xml文件规则什么的验证啊 获取比较麻烦,不知道你晕了没有)
xml还是包装成了Document委托给DocumentLoader去处理执行



11.现在又进入public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException ;
程序结果以上的处理,已经获取了xml文档的document,已经可以准备提取注册bean了。


12.经过documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
最终我们获取到了root,protected void doRegisterBeanDefinitions(Element root)这个方法,开始真正的解析已经处理过的资源。


13.解析完成后就是注册了,
debug到如下代码


14.可以看到在这里,把bean存到了beanDefinitionMap中,

对于beanDefinitionMap是什么,就是存在内存中的map,bean就存在里面供外部获取。


跟踪了这么多的源代码,肯定有点乱。做下总结吧。
Spring中bean的加载过程
1.获取配置文件资源
2.对获取的xml资源进行一定的处理检验
3.处理包装资源
4.解析处理包装过后的资源
5.加载提取bean并注册(添加到beanDefinitionMap中)

至于bean的获取,那就比上面的简单多了。
断点进入AbstractBeanFactory


入口
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
进入之后
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {// Quick check on the concurrent map first, with minimal locking.
   RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
   if (mbd != null) {return mbd;
   }return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
再进入
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
我们发现又进入了
DefaultListableBeanFactory.java,是不是有种熟悉的感觉。
当你看到这条语句,你就豁然开朗了,
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
就是之前加载bean放入到的map吗?
其实整个过程还是比较容易理解的,就是里面的包装解析很复杂

这篇关于spring的bean加载的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089603

相关文章

Spring boot整合dubbo+zookeeper的详细过程

《Springboot整合dubbo+zookeeper的详细过程》本文讲解SpringBoot整合Dubbo与Zookeeper实现API、Provider、Consumer模式,包含依赖配置、... 目录Spring boot整合dubbo+zookeeper1.创建父工程2.父工程引入依赖3.创建ap

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

Spring Boot spring-boot-maven-plugin 参数配置详解(最新推荐)

《SpringBootspring-boot-maven-plugin参数配置详解(最新推荐)》文章介绍了SpringBootMaven插件的5个核心目标(repackage、run、start... 目录一 spring-boot-maven-plugin 插件的5个Goals二 应用场景1 重新打包应用

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

创建Java keystore文件的完整指南及详细步骤

《创建Javakeystore文件的完整指南及详细步骤》本文详解Java中keystore的创建与配置,涵盖私钥管理、自签名与CA证书生成、SSL/TLS应用,强调安全存储及验证机制,确保通信加密和... 目录1. 秘密键(私钥)的理解与管理私钥的定义与重要性私钥的管理策略私钥的生成与存储2. 证书的创建与

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直

SpringBoot中如何使用Assert进行断言校验

《SpringBoot中如何使用Assert进行断言校验》Java提供了内置的assert机制,而Spring框架也提供了更强大的Assert工具类来帮助开发者进行参数校验和状态检查,下... 目录前言一、Java 原生assert简介1.1 使用方式1.2 示例代码1.3 优缺点分析二、Spring Fr

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件