原创文章,转发请标注https://www.cnblogs.com/boycelee/p/12595884.html

分析例子

启动类

Application,使用的是ClassPathXmlApplicationContext来加载xml文件

  1. /**
  2. * @author jianw.li
  3. * @date 2020/3/16 11:53 PM
  4. * @Description: TODO
  5. */
  6. public class MyApplication {
  7. private static final String CONFIG_LOCATION = "classpath:application_context.xml";
  8. private static final String BEAN_NAME = "hello";
  9. public static void main(String[] args) {
  10. ApplicationContext ac = new ClassPathXmlApplicationContext(CONFIG_LOCATION);
  11. Hello hello = (Hello) ac.getBean(BEAN_NAME);
  12. hello.sayHello();
  13. }
  14. }

Bean

  1. /**
  2. * @author jianw.li
  3. * @date 2020/3/16 11:53 PM
  4. * @Description: TODO
  5. */
  6. public class Hello {
  7. public void sayHello() {
  8. System.out.println("Hello World");
  9. }
  10. }

配置文件

​ 在resources下建立名为classpath:application_context.xml的配置文件,并配置好Bean

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="hello" class="com.boyce.bean.Hello"></bean>
  6. </beans>

总体结构

ClassPathXmlApplicationContext继承体系如下:

IoC总体结构图如下:

源码分析

BeanFactory获取

ClassPathXmlApplicationContext

  1. //构造函数,创建ClassPathXmlApplicationContext,其中configLocation为Bean所在的文件路径
  2. public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
  3. this(new String[] {configLocation}, true, null);
  4. }
  5. public ClassPathXmlApplicationContext(
  6. String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
  7. throws BeansException {
  8. //null
  9. super(parent);
  10. //设置配置路径至ApplicationContext中
  11. setConfigLocations(configLocations);
  12. if (refresh) {
  13. //核心方法,refresh会将旧的ApplicaionContext销毁
  14. refresh();
  15. }
  16. }

AbstractApplicationContext

refresh

​ 核心方法,refresh销毁旧ApplicationContext,生成新的ApplicationContext

  1. @Override
  2. public void refresh() throws BeansException, IllegalStateException {
  3. //加锁.没有明确对象,只是想让一段代码同步,可以创建Object startupShutdownMonitor = new Object()
  4. synchronized (this.startupShutdownMonitor) {
  5. // 为context刷新准备.设置启动时间,设置激活状态等
  6. prepareRefresh();
  7. // 告知子类刷新内部bean factory.
  8. // 获取BeanFactory,默认实现DefaultListableBeanFactory
  9. // 加载BeanDefinition,并注册至BeanDefinitionRegistry
  10. // (核心)
  11. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  12. // Prepare the bean factory for use in this context.
  13. // 进行BeanFactory的预准备工作,对BeanFactory进行信息设置
  14. prepareBeanFactory(beanFactory);
  15. try {
  16. // Allows post-processing of the bean factory in context subclasses.
  17. // BeanFactory准备工作
  18. postProcessBeanFactory(beanFactory);
  19. // Invoke factory processors registered as beans in the context.
  20. // 实例化实现BeanFactoryPostProcessor接口的Bean,并调用接口方法
  21. invokeBeanFactoryPostProcessors(beanFactory);
  22. // Register bean processors that intercept bean creation.
  23. // 注册BeanPostProcessors(Bean的后置处理器),创建Bean的前后等执行
  24. registerBeanPostProcessors(beanFactory);
  25. // Initialize message source for this context.
  26. // 初始化MessageSource组件,国际化相关功能
  27. initMessageSource();
  28. // Initialize event multicaster for this context.
  29. // 初始化事件派发器
  30. initApplicationEventMulticaster();
  31. // Initialize other special beans in specific context subclasses.
  32. // 子类重写,在容器刷新时可以自定义逻辑;如创建Tomcat、Jetty等Web服务器
  33. onRefresh();
  34. // Check for listener beans and register them.
  35. // 注册应用的监听器(注册实现ApplicationListener接口的监听器bean)
  36. registerListeners();
  37. // Instantiate all remaining (non-lazy-init) singletons.
  38. // 初始化所有非懒加载单例bean
  39. // 属性填充
  40. // 初始化方法的调用(例如afterPropertiesSet、init-method方法)
  41. // 调用BeanPostProcessor(后置处理器)对实例bean进行后置处理
  42. // (核心)
  43. finishBeanFactoryInitialization(beanFactory);
  44. // Last step: publish corresponding event.
  45. //广播初始化完成
  46. finishRefresh();
  47. }
  48. catch (BeansException ex) {
  49. if (logger.isWarnEnabled()) {
  50. logger.warn("Exception encountered during context initialization - " +
  51. "cancelling refresh attempt: " + ex);
  52. }
  53. // Destroy already created singletons to avoid dangling resources.
  54. destroyBeans();
  55. // Reset 'active' flag.
  56. cancelRefresh(ex);
  57. // Propagate exception to caller.
  58. throw ex;
  59. }
  60. finally {
  61. // Reset common introspection caches in Spring's core, since we
  62. // might not ever need metadata for singleton beans anymore...
  63. resetCommonCaches();
  64. }
  65. }
  66. }
obtainFreshBeanFactory

​ 告知子类刷新内部bean factory.

​ 核心方法,初始化BeanFactory、加载Bean、注册Bean

  1. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
  2. //刷新Bean工厂,关闭并销毁旧BeanFacroty
  3. refreshBeanFactory();
  4. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  5. if (logger.isDebugEnabled()) {
  6. logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
  7. }
  8. return beanFactory;
  9. }
refreshBeanFactory

​ 关闭并销毁旧BeanFactory,创建与初始化新BeanFactory。为什么是DefaultListableBeanFactory?

  1. @Override
  2. protected final void refreshBeanFactory() throws BeansException {
  3. // 判断是否已有BeanFactory
  4. if (hasBeanFactory()) {
  5. // 如果已有,则销毁beans且关闭BeanFactory
  6. destroyBeans();
  7. closeBeanFactory();
  8. }
  9. try {
  10. //初始化DefaultListableBeanFactory,为什么选择实例化DefaultListableBeanFactory?而不是其他的Bean工厂
  11. DefaultListableBeanFactory beanFactory = createBeanFactory();
  12. //Bean工厂序列化设置id
  13. beanFactory.setSerializationId(getId());
  14. //定制Bean工厂,设置不允许覆盖Bean,不允许循环依赖等
  15. customizeBeanFactory(beanFactory);
  16. //加载BeanDefinitions
  17. loadBeanDefinitions(beanFactory);
  18. //此处synchronized块与#hasBeanFactory中的synchronized块存在关联,此处锁住之后hasBeanFactory中的synchronized块将等待
  19. //避免beanFactory未销毁或未关闭的情况
  20. synchronized (this.beanFactoryMonitor) {
  21. this.beanFactory = beanFactory;
  22. }
  23. }
  24. catch (IOException ex) {
  25. throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
  26. }
  27. }
customizeBeanFactory

​ 定制BeanFactory。设置Bean覆盖、循环依赖等。什么是循环依赖?

  1. protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
  2. if (this.allowBeanDefinitionOverriding != null) {
  3. //默认值为false不允许对Bean进行覆盖
  4. beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
  5. }
  6. if (this.allowCircularReferences != null) {
  7. //默认值为false,不允许循环依赖
  8. beanFactory.setAllowCircularReferences(this.allowCircularReferences);
  9. }
  10. }

BeanFactory获取时序图

BeanDefinition加载注册

AbstractXmlApplicationContext

loadBeanDefinitions
  1. @Override
  2. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
  3. // Create a new XmlBeanDefinitionReader for the given BeanFactory.
  4. // 为BeanFactory创建XmlBeanDefinitionReader对象,用于解析xml对象
  5. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
  6. // Configure the bean definition reader with this context's
  7. // resource loading environment.
  8. // 为beanDefinitionReader设置环境信息
  9. beanDefinitionReader.setEnvironment(this.getEnvironment());
  10. beanDefinitionReader.setResourceLoader(this);
  11. beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
  12. // Allow a subclass to provide custom initialization of the reader,
  13. // then proceed with actually loading the bean definitions.
  14. // 允许子类自定义初始化阅读器
  15. initBeanDefinitionReader(beanDefinitionReader);
  16. //加载BeanDefinition
  17. loadBeanDefinitions(beanDefinitionReader);
  18. }
loadBeanDefinitions
  1. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
  2. Resource[] configResources = getConfigResources();
  3. if (configResources != null) {
  4. //加载资源对象,最终还是会回到这种方式去加载bean.
  5. reader.loadBeanDefinitions(configResources);
  6. }
  7. String[] configLocations = getConfigLocations();
  8. if (configLocations != null) {
  9. //加载资源路径吗
  10. reader.loadBeanDefinitions(configLocations);
  11. }
  12. }

AbstractBeanDefinitionReader

loadBeanDefinitions
  1. @Override
  2. public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
  3. Assert.notNull(locations, "Location array must not be null");
  4. int counter = 0;
  5. //循环配置文件路径
  6. for (String location : locations) {
  7. counter += loadBeanDefinitions(location);
  8. }
  9. return counter;
  10. }
  1. public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
  2. ResourceLoader resourceLoader = getResourceLoader();
  3. if (resourceLoader == null) {
  4. throw new BeanDefinitionStoreException(
  5. "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
  6. }
  7. if (resourceLoader instanceof ResourcePatternResolver) {
  8. // Resource pattern matching available.
  9. try {
  10. // 将xml转为Resource,所以上面的两种资源加载方式,最终都会回到Resource为参数的加载方式
  11. Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
  12. // 加载资源配置中的BeanDeinition对象,并返回数量
  13. int loadCount = loadBeanDefinitions(resources);
  14. if (actualResources != null) {
  15. for (Resource resource : resources) {
  16. actualResources.add(resource);
  17. }
  18. }
  19. if (logger.isDebugEnabled()) {
  20. logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
  21. }
  22. return loadCount;
  23. }
  24. catch (IOException ex) {
  25. throw new BeanDefinitionStoreException(
  26. "Could not resolve bean definition resource pattern [" + location + "]", ex);
  27. }
  28. }
  29. else {
  30. // Can only load single resources by absolute URL.
  31. Resource resource = resourceLoader.getResource(location);
  32. int loadCount = loadBeanDefinitions(resource);
  33. if (actualResources != null) {
  34. actualResources.add(resource);
  35. }
  36. if (logger.isDebugEnabled()) {
  37. logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
  38. }
  39. return loadCount;
  40. }
  41. }
  1. @Override
  2. public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
  3. // 就算是入参为location的loadBeanDefinitions,最终也会回到入参为resource的loadBeanDefinitions中
  4. Assert.notNull(resources, "Resource array must not be null");
  5. int counter = 0;
  6. for (Resource resource : resources) {
  7. counter += loadBeanDefinitions(resource);
  8. }
  9. return counter;
  10. }

XmlBeanDefinitionReader

loadBeanDefinitions

​ 从详细的XML文件中加载Bean

  1. public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
  2. Assert.notNull(encodedResource, "EncodedResource must not be null");
  3. if (logger.isInfoEnabled()) {
  4. logger.info("Loading XML bean definitions from " + encodedResource.getResource());
  5. }
  6. //用于存储编译过的Reource
  7. Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
  8. if (currentResources == null) {
  9. currentResources = new HashSet<>(4);
  10. this.resourcesCurrentlyBeingLoaded.set(currentResources);
  11. }
  12. if (!currentResources.add(encodedResource)) {
  13. throw new BeanDefinitionStoreException(
  14. "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
  15. }
  16. try {
  17. InputStream inputStream = encodedResource.getResource().getInputStream();
  18. try {
  19. // 将xml文件流封装为InputSource对象
  20. InputSource inputSource = new InputSource(inputStream);
  21. if (encodedResource.getEncoding() != null) {
  22. inputSource.setEncoding(encodedResource.getEncoding());
  23. }
  24. // 执行加载BeanDefinitions
  25. return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
  26. }
  27. finally {
  28. inputStream.close();
  29. }
  30. }
  31. catch (IOException ex) {
  32. throw new BeanDefinitionStoreException(
  33. "IOException parsing XML document from " + encodedResource.getResource(), ex);
  34. }
  35. finally {
  36. currentResources.remove(encodedResource);
  37. if (currentResources.isEmpty()) {
  38. this.resourcesCurrentlyBeingLoaded.remove();
  39. }
  40. }
  41. }
doLoadBeanDefinitions

​ 从xml文件中加载bean,将xml转为Document并注册Bean

  1. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
  2. throws BeanDefinitionStoreException {
  3. try {
  4. // 将xml转为Document
  5. Document doc = doLoadDocument(inputSource, resource);
  6. // 解析document对象,封装BeanDefinition对象并注册Bean
  7. return registerBeanDefinitions(doc, resource);
  8. }
  9. ...
  10. }
registerBeanDefinitions

​ 计算从当前配置文件中加载bean的数量

  1. public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
  2. BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
  3. // 获取已注册的BeanDefinition的数量
  4. int countBefore = getRegistry().getBeanDefinitionCount();
  5. // 注册BeanDefinition
  6. documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
  7. // 计算新注册BeanDefinition的数量并返回
  8. return getRegistry().getBeanDefinitionCount() - countBefore;
  9. }

DefaultBeanDefinitionDocumentReader

registerBeanDefinitions

​ 从“spring-beans” xsd中解析bean。什么是xsd?XML结构定义 ( XML Schemas Definition)

  1. @Override
  2. public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
  3. this.readerContext = readerContext;
  4. logger.debug("Loading bean definitions");
  5. Element root = doc.getDocumentElement();
  6. // 执行注册BeanDefinitions
  7. doRegisterBeanDefinitions(root);
  8. }
doRegisterBeanDefinitions

​ 从根节点开始注册每一个Bean

  1. /**
  2. * Register each bean definition within the given root {@code <beans/>} element.
  3. * 从根节点开始注册每一个Bean
  4. */
  5. protected void doRegisterBeanDefinitions(Element root) {
  6. // Any nested <beans> elements will cause recursion in this method. In
  7. // order to propagate and preserve <beans> default-* attributes correctly,
  8. // keep track of the current (parent) delegate, which may be null. Create
  9. // the new (child) delegate with a reference to the parent for fallback purposes,
  10. // then ultimately reset this.delegate back to its original (parent) reference.
  11. // this behavior emulates a stack of delegates without actually necessitating one.
  12. //可以通过spring.profiles.active设定当前环境激活的profile,例如配置prod,可以通过@ActiveProfiles配置
  13. // 解析bean定义
  14. // 委托模式
  15. BeanDefinitionParserDelegate parent = this.delegate;
  16. this.delegate = createDelegate(getReaderContext(), root, parent);
  17. if (this.delegate.isDefaultNamespace(root)) {
  18. //获取元素中profile属性,可以通过xml或@Profile设置当前bean所属的profile
  19. String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
  20. //不能做profile属性则直接跳过
  21. if (StringUtils.hasText(profileSpec)) {
  22. //配置多profile
  23. String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
  24. profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
  25. //元素中的profile是否是环境指定的profiles之一
  26. if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
  27. if (logger.isInfoEnabled()) {
  28. logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
  29. "] not matching: " + getReaderContext().getResource());
  30. }
  31. //不在当前环境指定的profile中则return
  32. return;
  33. }
  34. }
  35. }
  36. preProcessXml(root);
  37. // 解析元素
  38. parseBeanDefinitions(root, this.delegate);
  39. postProcessXml(root);
  40. this.delegate = parent;
  41. }
parseBeanDefinitions

​ 从文档根节点开始解析元素,import、alias、bean等

  1. /**
  2. * Parse the elements at the root level in the document:
  3. * "import", "alias", "bean".
  4. * @param root the DOM root element of the document
  5. */
  6. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
  7. if (delegate.isDefaultNamespace(root)) {
  8. NodeList nl = root.getChildNodes();
  9. for (int i = 0; i < nl.getLength(); i++) {
  10. Node node = nl.item(i);
  11. if (node instanceof Element) {
  12. Element ele = (Element) node;
  13. if (delegate.isDefaultNamespace(ele)) {
  14. //解析default namespace下的元素(例如:<import>、<alias>、<beans>、<bean>)
  15. parseDefaultElement(ele, delegate);
  16. }
  17. else {
  18. //解析Custom元素(例如:<mvc>、<context>、<aop>),自定义标签
  19. delegate.parseCustomElement(ele);
  20. }
  21. }
  22. }
  23. }
  24. else {
  25. delegate.parseCustomElement(root);
  26. }
  27. }
parseDefaultElement

​ 解析default namespace下的元素(例如:、、、)

  1. private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
  2. if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
  3. importBeanDefinitionResource(ele);
  4. }
  5. else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
  6. processAliasRegistration(ele);
  7. }
  8. else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
  9. //解析bean元素为BeanDefinition
  10. processBeanDefinition(ele, delegate);
  11. }
  12. else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
  13. // recurse
  14. doRegisterBeanDefinitions(ele);
  15. }
  16. }
processBeanDefinition

​ 获取bean元素解析并注册

  1. /**
  2. * Process the given bean element, parsing the bean definition
  3. * and registering it with the registry.
  4. * 获取bean元素解析并注册
  5. */
  6. protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
  7. //解析bean元素成BeanDefinition,并将BeanDefinition封装成BeanDefinitionHolder对象
  8. BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
  9. if (bdHolder != null) {
  10. bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
  11. try {
  12. // Register the final decorated instance.
  13. //注册装饰的实例,完成BeanDefinition注册
  14. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
  15. }
  16. catch (BeanDefinitionStoreException ex) {
  17. getReaderContext().error("Failed to register bean definition with name '" +
  18. bdHolder.getBeanName() + "'", ele, ex);
  19. }
  20. // Send registration event.
  21. //发送注册事件
  22. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
  23. }

BeanDefinitionReaderUtils

registerBeanDefinition
  1. public static void registerBeanDefinition(
  2. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
  3. throws BeanDefinitionStoreException {
  4. // Register bean definition under primary name.
  5. String beanName = definitionHolder.getBeanName();
  6. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
  7. // Register aliases for bean name, if any.
  8. String[] aliases = definitionHolder.getAliases();
  9. if (aliases != null) {
  10. for (String alias : aliases) {
  11. registry.registerAlias(beanName, alias);
  12. }
  13. }
  14. }

DefaultListableBeanFactory

registerBeanDefinition
  1. @Override
  2. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
  3. throws BeanDefinitionStoreException {
  4. Assert.hasText(beanName, "Bean name must not be empty");
  5. Assert.notNull(beanDefinition, "BeanDefinition must not be null");
  6. if (beanDefinition instanceof AbstractBeanDefinition) {
  7. try {
  8. ((AbstractBeanDefinition) beanDefinition).validate();
  9. }
  10. catch (BeanDefinitionValidationException ex) {
  11. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  12. "Validation of bean definition failed", ex);
  13. }
  14. }
  15. BeanDefinition oldBeanDefinition;
  16. //beanDefinitionMap放置所有注册的Bean
  17. oldBeanDefinition = this.beanDefinitionMap.get(beanName);
  18. //如果bean名已存在
  19. if (oldBeanDefinition != null) {
  20. //不允许覆盖bean
  21. if (!isAllowBeanDefinitionOverriding()) {
  22. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  23. "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
  24. "': There is already [" + oldBeanDefinition + "] bound.");
  25. }
  26. //通过比较BeanRole.判断谁覆盖谁
  27. else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
  28. // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
  29. if (this.logger.isWarnEnabled()) {
  30. this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
  31. "' with a framework-generated bean definition: replacing [" +
  32. oldBeanDefinition + "] with [" + beanDefinition + "]");
  33. }
  34. }
  35. //新bean覆盖旧bean
  36. else if (!beanDefinition.equals(oldBeanDefinition)) {
  37. if (this.logger.isInfoEnabled()) {
  38. this.logger.info("Overriding bean definition for bean '" + beanName +
  39. "' with a different definition: replacing [" + oldBeanDefinition +
  40. "] with [" + beanDefinition + "]");
  41. }
  42. }
  43. else {
  44. if (this.logger.isDebugEnabled()) {
  45. this.logger.debug("Overriding bean definition for bean '" + beanName +
  46. "' with an equivalent definition: replacing [" + oldBeanDefinition +
  47. "] with [" + beanDefinition + "]");
  48. }
  49. }
  50. //将bean放置beanDefinitionMap中
  51. this.beanDefinitionMap.put(beanName, beanDefinition);
  52. }
  53. //beanName没有与beanDefinitionMap中的重复
  54. else {
  55. //非正常情况下,其他的Bean已经初始化,如果已经有bean初始化,则使用者已经在进行业务操作,无法保证对beanDefinitionMap、beanDefinitionNames、manualSingletonNames进行操作的一些列动作的线程安全,所以需要加锁。参考:https://blog.csdn.net/qq_41907991/article/details/97614337
  56. if (hasBeanCreationStarted()) {
  57. // Cannot modify startup-time collection elements anymore (for stable iteration)
  58. synchronized (this.beanDefinitionMap) {
  59. this.beanDefinitionMap.put(beanName, beanDefinition);
  60. List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
  61. updatedDefinitions.addAll(this.beanDefinitionNames);
  62. updatedDefinitions.add(beanName);
  63. this.beanDefinitionNames = updatedDefinitions;
  64. if (this.manualSingletonNames.contains(beanName)) {
  65. Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
  66. updatedSingletons.remove(beanName);
  67. this.manualSingletonNames = updatedSingletons;
  68. }
  69. }
  70. }
  71. else {
  72. // Still in startup registration phase
  73. //bean放置beanDefinitionMap中
  74. this.beanDefinitionMap.put(beanName, beanDefinition);
  75. //记录bean名称
  76. this.beanDefinitionNames.add(beanName);
  77. //bean不需要手动注册
  78. this.manualSingletonNames.remove(beanName);
  79. }
  80. this.frozenBeanDefinitionNames = null;
  81. }
  82. if (oldBeanDefinition != null || containsSingleton(beanName)) {
  83. resetBeanDefinition(beanName);
  84. }
  85. }

BeanDefinition加载注册流程图

总结

​ 至此已经完成了IoC容器的初始化。将xml文件中的bean元素解析为Bean,将Bean注册至注册中心,并发送注册事件。DefaultListableBeanFactory建立Bean配置信息,这些信息都存放在BeanDefinitionMap中,由IoC容器来维护。

​ 最后,懂得不多,做得很少。文章肯定又不少错误,如大家发现麻烦及时指出,为了避免误导更多人,我也会及时学习并修改!

引用参考

[1]《Spring技术内幕》

[2]https://www.javadoop.com/post/spring-ioc

[3]https://github.com/seaswalker/spring-analysis/blob/master/note/Spring.md#classpathxmlapplicationcontext

SpringFramework之IoC容器初始化的更多相关文章

  1. 【spring源码分析】IOC容器初始化(一)

    前言:spring主要就是对bean进行管理,因此IOC容器的初始化过程非常重要,搞清楚其原理不管在实际生产或面试过程中都十分的有用.在[spring源码分析]准备工作中已经搭建好spring的环境, ...

  2. 【spring源码分析】IOC容器初始化(三)

    前言:在[spring源码分析]IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程. XmlBeanDefinitionReader#registerB ...

  3. 【spring源码分析】IOC容器初始化(四)

    前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...

  4. 【Spring源码解析】—— 结合SpringMVC过程理解IOC容器初始化

    关于IOC容器的初始化,结合之前SpringMVC的demo,对其过程进行一个相对详细的梳理,主要分为几个部分: 一.IOC的初始化过程,结合代码和debug过程重点说明 1. 为什么要debug? ...

  5. 【spring源码分析】IOC容器初始化——查漏补缺(一)

    前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...

  6. 整理在Spring IOC容器初始化后可以处理特定逻辑的多种实现方式

    Spring框架的核心是依赖注入.切面:Spring Boot是在Spring框架的基础上为其提供许多默认配置.默认约定(约定优于配置),从而达到减少或减化配置进而可开箱即用.快速上手:Spring ...

  7. Spring IoC容器初始化过程学习

    IoC容器是什么?IoC文英全称Inversion of Control,即控制反转,我么可以这么理解IoC容器: 把某些业务对象的的控制权交给一个平台或者框架来同一管理,这个同一管理的平台可以称为I ...

  8. spring源码学习之路---深度分析IOC容器初始化过程(四)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近由于工作和生活,学习耽搁 ...

  9. spring源码 — 一、IoC容器初始化

    IoC容器初始化 注意:本次的spring源码是基于3.1.1.release版本 容器:具有获取Bean功能--这是最基本功能,也是BeanFactory接口定义的主要行为,在添加了对于资源的支持之 ...

随机推荐

  1. Spring5源码分析(1)设计思想与结构

    1 源码地址(带有中文注解)git@github.com:yakax/spring-framework-5.0.2.RELEASE--.git Spring 的设计初衷其实就是为了简化我们的开发 基于 ...

  2. 一劳永逸的解决AFNetworking3.0网络请求问题

    AFNetworking在iOS网络请求第三方库中占据着半壁江山,前段时间将AFNetworking进行了3.0版本的迁移,运用面向对象的设计将代码进行封装整合,这篇文章主要为还在寻找AFNetwor ...

  3. SGD与Adam识别MNIST数据集

    几种常见的优化函数比较:https://blog.csdn.net/w113691/article/details/82631097 ''' 基于Adam识别MNIST数据集 ''' import t ...

  4. Class file version does not support constant tag 16 in class file

    启动服务时提示 Caused by: java.lang.ClassFormatError: Class file version does not support constant tag 16 i ...

  5. NIO-EPollSelectorIpml源码分析

    目录 NIO-EPollSelectorIpml源码分析 目录 前言 初始化EPollSelectorProvider 创建EPollSelectorImpl EPollSelectorImpl结构 ...

  6. iOS Swift 开发语言之初接触,纯代码创建UIView,UITableView,UICollectionView

    1. 初始化Label设置AttributeString override func viewDidLoad() { let label = UILabel(frame:CGRect(x:,y:,wi ...

  7. py基础之数据类型及基本语法

    '''python中有五种数据类型,分别是整数.浮点数.字符串.布尔值.空值'''a = 1b = 2.0c = 'hello,world'print (a,b,c)#a是整数,b是浮点数,c是字符串 ...

  8. C与ARM汇编结合实现mini2440串口uart简单程序

    最近学完了ARM的一些基础知识,开始在mini2440上开发一些简单的程序,串口发送程序是一开始涉及多个寄存器的例子,稍有繁多的步骤应该是开发过程中要慢慢适应的境况 下面的程序的目的是实现mini24 ...

  9. 关于Html+css阶段学习总结

    一.学习经历 进入大学不久,就加入了社团,从而对前端有了一个初步的了解,之后也做过一些学校的官网,积累了一些微小的经验. 到了大二的时候,学校开设了专门的html+css课程,从中也学到许多新的htm ...

  10. JavaScript判断一个对象是否为空

    本文介绍了判断一个对象是否为空的几种方法 测试用例 test1 = 1; test2 = {}; test3 = {a:1,b:2} 1. 判断Object.keys()的长度 function _i ...