spring源码解读

news2024/11/26 1:43:21

深入了解Spring

Bean

Java bean和spring bean区别

  • Java bean的属性私有,只能通过get和set方法来对属性进行操作。
  • Spring bean是由spring容器生成和管理的对象。

spring Bean的定义方式

  • xml文件 。 声明式。

  • @bean注解。 声明式。

  • @component注解。声明式。

  • @BeanDefinition。编程式

    • AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
      AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
      beanDefinition.setBeanClass(User.class);
      annotationConfigApplicationContext.registerBeanDefinition("user",beanDefinition);
      annotationConfigApplicationContext.refresh();
      //取出
      User user=annotationConfigApplicationContext.getBean("user",User.class);
      
  • 实现FactoryBean接口

    • 自定义工厂类

      public class ZhuFactoryBean implements FactoryBean {
          //获取对象
          public Object getObject() throws Exception {
              Person person=new Person();
              return person;
          }
          //获取类型
          public Class<?> getObjectType() {
              return Person.class;
          }
      
          public boolean isSingleton() {
              return false;
          }
      }
      
      
      
      
    • 定义bean和取出bean

      AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
      AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
      beanDefinition.setBeanClass(ZhuFactoryBean.class);
      //注册工厂类会将工厂类本身添加进入容器,也会将工厂添加的bean注入容器
      annotationConfigApplicationContext.registerBeanDefinition("person",beanDefinition);
      annotationConfigApplicationContext.refresh();
      //取出工厂类
      ZhuFactoryBean zhuFactoryBean=annotationConfigApplicationContext.getBean("&person",ZhuFactoryBean.class);
      //取出工厂定义的bean
      Person person=annotationConfigApplicationContext.getBean("person",Person.class);
      System.out.println(zhuFactoryBean);
      System.out.println(person);
      
  • 使用supplier定义bean

    • annotationConfigApplicationContext.registerBean(User.class, new Supplier<User>() {
          @Override
          public User get() {
              User user=new User();
              user.setAge(11);
              return user;
          }
      });
      

spring容器

单例池

  • spring中单例池存放的是单例bean,内部数据结构为concurrentHashMap,spring源码中的定义为Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256)。map的key为name,value为bean对象。它用于保存非懒加载的单例Bean。如果对象使用了AOP完成了一些操作,那么放入单例池的就是代理对象而不是他本身。

Bean生命周期

思维导图

  • 简单来说:

preview

流程总结

通过BeanDefinitionReader接口将xml或者注解配置的对象转换成BeanFactory中的beanDefinitionMap中的beanDefination。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ldqJlZOb-1685347461590)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718114056465.png)]**—>之后beanFactoryPostProcessor接口的postprocessorFactoryBean方法可以获取到对factoryBean的信息,也就能对beanDefination进行一些操作,例如对xml文件中的占位符进行拼接、对注解的扫描(例如@component修饰的类转化为一个beanDefinition对象)。----->**创建对象,过程可以分为下图两步。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YsWWdlRu-1685347461591)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210717191046208.png)]

spring在实例化的时候是采用反射的方式实例化对象的,之后填充属性。**---->**调用Aware接口中的方法(Aware接口可以帮助自定义对象获取容器类对象(ApplicationContext、BeanFactory等),如简单对象通过实现ApplicationContextAware接口,可以让这个对象get到ApplicationContext容器)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eZvWHet-1685347461592)(C:\Users\Ric\AppData\Local\Temp\企业微信截图_16265793448073.png)]

**---->**在bean创建之前调用before方法,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PYejt2Df-1685347461592)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718112814382.png)]之后调用init方法,之后调用after方法(通过beanPostProcessor接口实现AOP,接口的实现类会创建代理对象)。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G87HYqDS-1685347461593)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718112925284.png)]

**----》**之后就是一个完整的bean对象了。

思维导图:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hLy6FkuI-1685347461593)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210718114858308.png)]

debug spring源码

debug入口

源码地址:https://gitee.com/qurywu/spring_study.git

使用注解的方式创建bean对象,以及取出bean

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = annotationConfigApplicationContext.getBean(User.class);
user.run();

初始化IOC

创建AnnotationConfigApplicationContext对象和核心方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    //step1
    this();
    //step2
    this.register(componentClasses);
    //step3
    this.refresh();
}

step1:this()

 public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        this.beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
        this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, (ResourceLoader)null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

这段代码是一个构造函数,用于创建一个AnnotatedBeanDefinitionReader对象。AnnotatedBeanDefinitionReader是一个用于读取注解的BeanDefinition的类,它的作用是将注解转换为BeanDefinition对象并注册到BeanDefinitionRegistry中。

在构造函数中,首先设置了beanNameGenerator和scopeMetadataResolver的值,分别用于生成Bean的名称和解析Bean的作用域。然后通过断言确保传入的BeanDefinitionRegistry和Environment对象不为空,接着将它们赋值给成员变量registry和conditionEvaluator。

最后,调用AnnotationConfigUtils.registerAnnotationConfigProcessors方法,该方法会注册一些用于处理注解的BeanPostProcessor,例如AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor等。

step2:this.register(componentClasses)

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        abd.setInstanceSupplier(supplier);
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
        //如果传入了qualifiers参数,则遍历qualifiers数组,根据不同的限定符设置BeanDefinition的Primary、LazyInit或Qualifier属性。
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        int var10;
        int var11;
        if (qualifiers != null) {
            Class[] var9 = qualifiers;
            var10 = qualifiers.length;

            for(var11 = 0; var11 < var10; ++var11) {
                Class<? extends Annotation> qualifier = var9[var11];
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                } else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                } else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

        if (customizers != null) {
            BeanDefinitionCustomizer[] var13 = customizers;
            var10 = customizers.length;

            for(var11 = 0; var11 < var10; ++var11) {
                BeanDefinitionCustomizer customizer = var13[var11];
                customizer.customize(abd);
            }
        }

        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }
}

这段代码是一个私有方法,用于注册一个BeanDefinition。该方法接收一个beanClass参数,表示要注册的Bean的类型;一个name参数,表示Bean的名称;一个qualifiers参数,表示Bean的限定符;一个supplier参数,表示Bean的实例提供者;一个customizers参数,表示BeanDefinition的自定义器。

在方法中,首先创建一个AnnotatedGenericBeanDefinition对象,并通过conditionEvaluator判断是否应该跳过该BeanDefinition。然后设置BeanDefinition的实例提供者和作用域,并根据传入的name或使用beanNameGenerator生成Bean的名称。接着调用AnnotationConfigUtils.processCommonDefinitionAnnotations方法处理BeanDefinition上的常见注解。

如果传入了qualifiers参数,则遍历qualifiers数组,根据不同的限定符设置BeanDefinition的Primary、LazyInit或Qualifier属性。如果传入了customizers参数,则遍历customizers数组,调用每个BeanDefinitionCustomizer的customize方法对BeanDefinition进行自定义。

最后,将BeanDefinition封装为BeanDefinitionHolder对象,并根据作用域设置代理模式,最终通过BeanDefinitionReaderUtils.registerBeanDefinition方法将BeanDefinition注册到BeanDefinitionRegistry中。

register的实质是注册到BeanDefinitionMap中

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
        	//beanDefinition校验
            ((AbstractBeanDefinition)beanDefinition).validate();
        } catch (BeanDefinitionValidationException var8) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var8);
        }
    }
	//通过那么从beanDefinitionMap中拿到BeanDefinition
    BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
    //判断BeanDefinitionRegistry中是否已经存在同名的BeanDefinition对象。如果存在,则根据isAllowBeanDefinitionOverriding方法的返回值决定是否允许覆盖原有的BeanDefinition对象。如果允许覆盖,则根据BeanDefinition对象的角色和内容进行判断,如果需要覆盖则进行覆盖操作,否则不进行任何操作。
    if (existingDefinition != null) {
        if (!this.isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        }

        if (existingDefinition.getRole() < beanDefinition.getRole()) {
            if (this.logger.isInfoEnabled()) {
                this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }
        } else if (!beanDefinition.equals(existingDefinition)) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
            }
        } else if (this.logger.isTraceEnabled()) {
            this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
        }

        this.beanDefinitionMap.put(beanName, beanDefinition);
    } else {
    //如果不存在同名的BeanDefinition对象,则将BeanDefinition对象添加到BeanDefinitionRegistry中,并更新BeanDefinitionRegistry中的Bean名称列表。如果BeanDefinitionRegistry已经开始创建Bean,则需要进行同步操作
        if (this.hasBeanCreationStarted()) {
            synchronized(this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                this.removeManualSingletonName(beanName);
            }
        } else {
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            this.removeManualSingletonName(beanName);
        }

        this.frozenBeanDefinitionNames = null;
    }

    if (existingDefinition == null && !this.containsSingleton(beanName)) {
    //如果BeanDefinitionRegistry中不存在同名的单例Bean,则清除缓存。
        if (this.isConfigurationFrozen()) {
            this.clearByTypeCache();
        }
    } else {
        this.resetBeanDefinition(beanName);
    }

}

这段代码是BeanDefinitionRegistry接口的默认实现,用于将BeanDefinition对象注册到BeanDefinitionRegistry中。该方法接收两个参数,一个是Bean的名称,另一个是BeanDefinition对象。

在方法中,首先通过断言确保传入的Bean名称和BeanDefinition对象不为空。如果BeanDefinition对象是AbstractBeanDefinition的实例,则调用validate方法进行验证,如果验证失败则抛出BeanDefinitionStoreException异常。

接着判断BeanDefinitionRegistry中是否已经存在同名的BeanDefinition对象。如果存在,则根据isAllowBeanDefinitionOverriding方法的返回值决定是否允许覆盖原有的BeanDefinition对象。如果允许覆盖,则根据BeanDefinition对象的角色和内容进行判断,如果需要覆盖则进行覆盖操作,否则不进行任何操作。如果不允许覆盖,则抛出BeanDefinitionOverrideException异常。

如果不存在同名的BeanDefinition对象,则将BeanDefinition对象添加到BeanDefinitionRegistry中,并更新BeanDefinitionRegistry中的Bean名称列表。如果BeanDefinitionRegistry已经开始创建Bean,则需要进行同步操作。最后,如果BeanDefinitionRegistry中不存在同名的单例Bean,则清除缓存。

step3:refresh(核心)

调用finishRefresh()方法,完成应用程序上下文的刷新。public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
    //启动应用程序的启动步骤,记录“spring.context.refresh”步骤的开始时间。
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
        //调用prepareRefresh()方法,准备应用程序上下文的刷新。
        this.prepareRefresh();
        //调用obtainFreshBeanFactory()方法,获取一个新的bean工厂实例。
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        //调用prepareBeanFactory()方法,对bean工厂进行一些准备工作,例如设置类加载器、添加属性编辑器等。
        this.prepareBeanFactory(beanFactory);

        try {
        //调用postProcessBeanFactory()方法,对bean工厂进行后置处理,例如添加BeanFactoryPostProcessor等
            this.postProcessBeanFactory(beanFactory);
            //启动应用程序的启动步骤,记录“spring.context.beans.post-process”步骤的开始时间。
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            //调用invokeBeanFactoryPostProcessors()方法,调用所有注册的BeanFactoryPostProcessor的postProcessBeanFactory()方法。
            this.invokeBeanFactoryPostProcessors(beanFactory);
            //调用registerBeanPostProcessors()方法,注册所有BeanPostProcessor实例。
            this.registerBeanPostProcessors(beanFactory);
            // 结束“spring.context.beans.post-process”步骤。
            beanPostProcess.end();
            //调用initMessageSource()方法,初始化MessageSource实例。
            this.initMessageSource();
            //调用initApplicationEventMulticaster()方法,初始化ApplicationEventMulticaster实例。
            this.initApplicationEventMulticaster();
            //调用onRefresh()方法,执行应用程序上下文的自定义刷新逻辑。
            this.onRefresh();
            //调用registerListeners()方法,注册所有ApplicationListener实例。
            this.registerListeners();
            //调用finishBeanFactoryInitialization()方法,完成所有bean的实例化和初始化。
            this.finishBeanFactoryInitialization(beanFactory);
            //调用finishRefresh()方法,完成应用程序上下文的刷新。
            this.finishRefresh();
        } catch (BeansException var10) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
            }

            this.destroyBeans();
            this.cancelRefresh(var10);
            throw var10;
        } finally {
            this.resetCommonCaches();
            contextRefresh.end();
        }

    }
}

这段代码是Spring框架中的ApplicationContext接口的refresh()方法的实现。该方法用于刷新应用程序上下文,即重新加载所有bean定义并重新实例化所有单例bean。

具体来说,该方法的实现包括以下步骤:

  1. 获取启动和关闭监视器的锁,确保线程安全。
  2. 启动应用程序的启动步骤,记录“spring.context.refresh”步骤的开始时间。
  3. 调用prepareRefresh()方法,准备应用程序上下文的刷新。
  4. 调用obtainFreshBeanFactory()方法,获取一个新的bean工厂实例。
  5. 调用prepareBeanFactory()方法,对bean工厂进行一些准备工作,例如设置类加载器、添加属性编辑器等。
  6. 调用postProcessBeanFactory()方法,对bean工厂进行后置处理,例如添加BeanFactoryPostProcessor等。
  7. 启动应用程序的启动步骤,记录“spring.context.beans.post-process”步骤的开始时间。
  8. 调用invokeBeanFactoryPostProcessors()方法,调用所有注册的BeanFactoryPostProcessor的postProcessBeanFactory()方法。
  9. 调用registerBeanPostProcessors()方法,注册所有BeanPostProcessor实例。
  10. 结束“spring.context.beans.post-process”步骤。
  11. 调用initMessageSource()方法,初始化MessageSource实例。
  12. 调用initApplicationEventMulticaster()方法,初始化ApplicationEventMulticaster实例。
  13. 调用onRefresh()方法,执行应用程序上下文的自定义刷新逻辑。
  14. 调用registerListeners()方法,注册所有ApplicationListener实例。
  15. 调用finishBeanFactoryInitialization()方法,完成所有bean的实例化和初始化。
  16. 调用finishRefresh()方法,完成应用程序上下文的刷新。
  17. 如果在刷新过程中发生异常,记录警告日志,销毁所有bean实例,取消刷新并抛出异常。
  18. 重置所有公共缓存。
  19. 结束“spring.context.refresh”步骤。
refresh方法的理解
  • refresh方法一共包含十三个子方法

    • prepareRefresh方法,负责容器刷新前的准备工作,如:如设置容器启动时间,容器活跃状态、获取environment对象、准备监听器和事件的集合对象。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C4hQlEnS-1685347461594)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719154130999.png)]

      这段代码是Spring框架中的一个方法,用于准备应用程序上下文的刷新。下面是对代码的详细解读和优化建议:

      1. 第一行代码 this.startupDate = System.currentTimeMillis(); 用于记录应用程序上下文启动的时间,可以用于性能分析和调试。没有优化建议。
      2. ​ 第二行代码 this.closed.set(false); 用于将应用程序上下文的关闭状态设置为false,表示应用程序上下文没有关闭。没有优化建议。
      3. 第三行代码 this.active.set(true); 用于将应用程序上下文的活动状态设置为true,表示应用程序上下文正在运行。没有优化建议。
      4. 第四行代码 if (this.logger.isDebugEnabled()) {...} 用于判断日志级别是否为DEBUG,如果是,则记录“Refreshing”和应用程序上下文的名称或者对象。优化建议:可以将日志级别设置为INFO或WARN,避免在生产环境中记录过多的DEBUG级别日志。
      5. 第五行代码 this.initPropertySources(); 用于初始化应用程序上下文的属性源,可以用于加载配置文件和环境变量等。优化建议:可以使用更高效的方式加载配置文件,例如使用Spring Cloud Config Server或者使用本地缓存等。
      6. 第六行代码 this.getEnvironment().validateRequiredProperties(); 用于验证必需的属性是否已经设置,如果没有设置,则抛出异常。优化建议:可以使用更灵活的方式验证属性,例如使用Spring Boot的@ConfigurationProperties注解。
      7. 第七行代码 if (this.earlyApplicationListeners == null) {...} 用于初始化应用程序上下文的应用程序监听器,可以用于处理应用程序上下文的事件。优化建议:可以使用更高效的方式处理事件,例如使用异步事件处理器或者使用Spring Cloud Bus等。
      8. 第八行代码 this.earlyApplicationEvents = new LinkedHashSet(); 用于初始化应用程序上下文的应用程序事件,可以用于记录应用程序上下文的事件。没有优化建议。
  • obtainFreshBeanFactory方法,创建Bean工厂,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BpBkYE8n-1685347461595)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719154817721.png)]

        protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        this.refreshBeanFactory();
            return this.getBeanFactory();
    }
    
    这段代码是Spring框架中的一个方法,用于刷新应用程序上下文的Bean工厂。下面是对代码的详细解读:
      
    1. 方法签名
      
    方法签名表明该方法是一个final方法,不能被子类重写。该方法没有参数,抛出IllegalStateException异常。
      
    1. 方法实现
      
    该方法首先检查refreshed属性的值,如果为true,则抛出IllegalStateException异常,表示不支持多次刷新。否则,将refreshed属性设置为true,并将Bean工厂的序列化ID设置为应用程序上下文的ID
    
  
  
  
  ​		将Bean工厂的序列化ID设置为应用程序上下文的ID有什么用?
  ​    
  ​		在Java中,序列化是将对象转换为字节流的过程,以便在网络上传输或将其保存到磁盘上。在反序列化时,可以将字节流转换回对象。在序列化和反序列化过程中,Java使用一个称为序列化ID的标识符来标识对象的版本。如果序列化ID不匹配,则反序列化过程将失败。
  ​    
  在Bean工厂中,如果将序列化ID设置为应用程序上下文的ID,可以确保在反序列化时,Bean工厂的版本与应用程序上下文的版本匹配。这可以避免由于版本不匹配而导致的反序列化失败。
  ​    
  此外,将序列化ID设置为应用程序上下文的ID还可以提高代码的可维护性。如果应用程序上下文的ID发生更改,只需要更新Bean工厂的序列化ID即可,而不需要在整个代码库中搜索和更新所有与序列化相关的代码。
  ​    
  



  • prepareBeanFactory方法,填充beanFactory属性[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mrIKc7mb-1685347461595)(C:\Users\Ric\Desktop\每日总结\后端\spring\深入了解Spring\image-20210719155756828.png)]

        protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.setBeanClassLoader(this.getClassLoader());
            if (!shouldIgnoreSpel) {
            beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
            }
        
            beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
            beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
            beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
            beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
            beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
            beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
            beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
            beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
            beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
            beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
            beanFactory.registerResolvableDependency(ResourceLoader.class, this);
            beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
            beanFactory.registerResolvableDependency(ApplicationContext.class, this);
            beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
            if (!NativeDetector.inNativeImage() && beanFactory.containsBean("loadTimeWeaver")) {
                beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
                beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
            }
        
            if (!beanFactory.containsLocalBean("environment")) {
                beanFactory.registerSingleton("environment", this.getEnvironment());
            }
        
            if (!beanFactory.containsLocalBean("systemProperties")) {
                beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
            }
        
            if (!beanFactory.containsLocalBean("systemEnvironment")) {
                beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
            }
        
            if (!beanFactory.containsLocalBean("applicationStartup")) {
                beanFactory.registerSingleton("applicationStartup", this.getApplicationStartup());
            }
        
        
       }
    

    这段代码是Spring框架中的ApplicationContext的一个方法,用于准备BeanFactory,即对BeanFactory进行一些配置和初始化操作。具体来说,这个方法做了以下几件事情:

    1. 设置BeanClassLoader:将当前ApplicationContext的ClassLoader设置为BeanFactory的ClassLoader,以便BeanFactory能够加载Bean的类。
    2. 设置BeanExpressionResolver:如果shouldIgnoreSpel为false,则设置一个StandardBeanExpressionResolver作为BeanFactory的BeanExpressionResolver,用于解析Bean中的SpEL表达式。
    3. 注册PropertyEditorRegistrar:注册一个ResourceEditorRegistrar,用于将字符串类型的属性值转换为Resource类型。
    4. 添加BeanPostProcessor:添加一个ApplicationContextAwareProcessor,用于将ApplicationContext注入到实现了ApplicationContextAware接口的Bean中。
    5. 忽略某些依赖接口:忽略一些依赖接口,如EnvironmentAware、EmbeddedValueResolverAware等,这些接口的实现类会在后续的Bean创建过程中被自动注入。
    6. 注册可解析的依赖:注册一些可解析的依赖,如BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext等。
    7. 添加BeanPostProcessor:添加一个ApplicationListenerDetector,用于检测实现了ApplicationListener接口的Bean,并将其注册到ApplicationEventMulticaster中。
    8. 添加LoadTimeWeaverAwareProcessor:如果当前不是Native Image,并且BeanFactory中包含名为"loadTimeWeaver"的Bean,则添加一个LoadTimeWeaverAwareProcessor,用于将LoadTimeWeaver注入到实现了LoadTimeWeaverAware接口的Bean中。
    9. 注册environment、systemProperties、systemEnvironment、applicationStartup:如果BeanFactory中没有名为"environment"、"systemProperties"、"systemEnvironment"、"applicationStartup"的Bean,则将当前ApplicationContext中的Environment、SystemProperties、SystemEnvironment、ApplicationStartup注册为单例Bean。
    
    • postProcessBeanFactory方法,对beanFactory进行操作,但是是空实现。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jivhl8i7-1685347461596)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719160034279.png)]

    • invokeBeanFactoryPostProcessors方法,调用各种beanFactory处理器(beanFactoryPostProcessor)

      invokeBeanFactoryPostProcessors 是 Spring 框架中的一个方法,它的作用是在 BeanFactory 标准初始化之后,调用所有实现了 BeanFactoryPostProcessor 接口的类的 postProcessBeanFactory 方法,以便这些类可以对 BeanFactory 进行进一步的自定义修改。

      BeanFactoryPostProcessor 接口是 Spring 框架中的一个扩展点,它允许开发者在 BeanFactory 标准初始化之后,对 BeanFactory 进行自定义修改。这些修改可以包括添加、删除、修改 BeanDefinition,修改属性值等等。通过实现 BeanFactoryPostProcessor 接口,开发者可以在 Spring 容器启动时,对容器中的 Bean 进行进一步的自定义处理,以满足特定的业务需求。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x4UjyHCC-1685347461596)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719170112805.png)]

    • registerBeanPostProcessors方法,准备beanPostProcessor[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AZnvA9ZP-1685347461597)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719170549202.png)]

      public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
          String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
          int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
          beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
          List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList();
          List<BeanPostProcessor> internalPostProcessors = new ArrayList();
          List<String> orderedPostProcessorNames = new ArrayList();
          List<String> nonOrderedPostProcessorNames = new ArrayList();
          String[] var8 = postProcessorNames;
          int var9 = postProcessorNames.length;
      
          String ppName;
          BeanPostProcessor pp;
          for(int var10 = 0; var10 < var9; ++var10) {
              ppName = var8[var10];
              if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                  pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
                  priorityOrderedPostProcessors.add(pp);
                  if (pp instanceof MergedBeanDefinitionPostProcessor) {
                      internalPostProcessors.add(pp);
                  }
              } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                  orderedPostProcessorNames.add(ppName);
              } else {
                  nonOrderedPostProcessorNames.add(ppName);
              }
          }
      
          sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
          registerBeanPostProcessors(beanFactory, (List)priorityOrderedPostProcessors);
          List<BeanPostProcessor> orderedPostProcessors = new ArrayList(orderedPostProcessorNames.size());
          Iterator var14 = orderedPostProcessorNames.iterator();
      
          while(var14.hasNext()) {
              String ppName = (String)var14.next();
              BeanPostProcessor pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
              orderedPostProcessors.add(pp);
              if (pp instanceof MergedBeanDefinitionPostProcessor) {
                  internalPostProcessors.add(pp);
              }
          }
      
          sortPostProcessors(orderedPostProcessors, beanFactory);
          registerBeanPostProcessors(beanFactory, (List)orderedPostProcessors);
          List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList(nonOrderedPostProcessorNames.size());
          Iterator var17 = nonOrderedPostProcessorNames.iterator();
      
          while(var17.hasNext()) {
              ppName = (String)var17.next();
              pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
              nonOrderedPostProcessors.add(pp);
              if (pp instanceof MergedBeanDefinitionPostProcessor) {
                  internalPostProcessors.add(pp);
              }
          }
      
          registerBeanPostProcessors(beanFactory, (List)nonOrderedPostProcessors);
          sortPostProcessors(internalPostProcessors, beanFactory);
          registerBeanPostProcessors(beanFactory, (List)internalPostProcessors);
          beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
      }
      

      这里将所有的实现了beanpostprocessor接口的processor都注册进beanFactory中

      这段代码的作用是注册BeanPostProcessor,BeanPostProcessor是Spring框架中的一个扩展点,用于在Bean实例化、依赖注入、初始化等过程中对Bean进行增强处理。这个方法会根据BeanPostProcessor的实现类的不同,将其分为三类:实现了PriorityOrdered接口的、实现了Ordered接口的和其他的。然后对这三类BeanPostProcessor分别进行排序和注册。

      具体来说,这个方法会先获取所有实现了BeanPostProcessor接口的Bean的名称,然后根据实现的接口类型将其分为三类。实现了PriorityOrdered接口的BeanPostProcessor会被放入priorityOrderedPostProcessors集合中,实现了Ordered接口的BeanPostProcessor会被放入orderedPostProcessorNames集合中,其他的BeanPostProcessor会被放入nonOrderedPostProcessorNames集合中。

      接着,对priorityOrderedPostProcessors和orderedPostProcessorNames集合中的BeanPostProcessor进行排序,排序的规则是根据实现的接口类型和order属性值进行排序。排序后,将它们分别注册到beanFactory中。

      最后,将nonOrderedPostProcessorNames集合中的BeanPostProcessor注册到beanFactory中,并将实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor放入internalPostProcessors集合中。对internalPostProcessors集合中的BeanPostProcessor进行排序后,也将其注册到beanFactory中。

      最后,还会添加一个ApplicationListenerDetector的BeanPostProcessor到beanFactory中,用于检测Bean是否实现了ApplicationListener接口,如果实现了,则将其注册到事件监听器中。

      • initMessageSource方法,实现国际化

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XYSnvQ0P-1685347461598)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719171038203.png)] 这段代码的作用是初始化MessageSource,MessageSource是Spring框架中的一个接口,用于国际化和本地化处理。在Spring应用程序中,可以使用MessageSource接口来获取国际化的消息,以便在不同的语言环境下显示不同的消息。这个方法首先获取当前应用程序上下文中的BeanFactory,然后检查是否已经存在名为"messageSource"的Bean。如果存在,则将其赋值给messageSource属性,并检查是否存在父上下文,如果存在,则将父上下文中的MessageSource设置为当前MessageSource的父MessageSource。如果不存在,则创建一个DelegatingMessageSource实例,并将其设置为messageSource属性的值。然后将这个DelegatingMessageSource实例注册到BeanFactory中,并命名为"messageSource"。最后,如果日志级别为TRACE,则输出日志信息。

      • initApplicationEventMulticaster方法,初始化事件监听器、多路广播器。

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nRmBUlNs-1685347461598)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719171243808.png)]

        这段代码的作用是初始化ApplicationEventMulticaster,ApplicationEventMulticaster是Spring框架中的一个接口,用于管理和分发应用程序事件。在Spring应用程序中,可以使用ApplicationEventMulticaster接口来发布和监听应用程序事件。

        这个方法首先获取当前应用程序上下文中的BeanFactory,然后检查是否已经存在名为"applicationEventMulticaster"的Bean。如果存在,则将其赋值给applicationEventMulticaster属性。如果不存在,则创建一个SimpleApplicationEventMulticaster实例,并将其设置为applicationEventMulticaster属性的值。然后将这个SimpleApplicationEventMulticaster实例注册到BeanFactory中,并命名为"applicationEventMulticaster"。最后,如果日志级别为TRACE,则输出日志信息。

        发布和监听应用程序事件是Spring框架中的一个重要特性,它可以用于在应用程序中实现松耦合的组件之间的通信。下面是一些使用场景的例子:

        1. 用户注册成功后,需要发送一封欢迎邮件。可以在用户注册成功后,发布一个UserRegisteredEvent事件,然后监听这个事件的邮件发送组件就可以收到这个事件,并发送欢迎邮件。
        2. 在应用程序中,需要记录用户的操作日志。可以在用户执行操作时,发布一个UserOperationEvent事件,然后监听这个事件的日志记录组件就可以收到这个事件,并记录用户的操作日志。
        

        以下为自定义事件,并且发布事件、监听事件的demo代码:

        @Component
        public class AppEventListener implements ApplicationListener<CustomEvent> {
        
            @Override
            public void onApplicationEvent(CustomEvent event) {
                System.out.println("Received custom event - " + event.getMessage());
            }
        
            public static void main(String[] args) {
                AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
                context.register(AppEventListener.class);
                CustomEvent event = new CustomEvent(new Object(), "Hello, world!");
        
                context.refresh();
                context.publishEvent(event);
                // 应用程序运行中...
        
                context.close();
            }
        }
        

        @Component
        public class CustomEvent extends ApplicationEvent {
            private String message;
        
            public CustomEvent(Object source, String message) {
                super(source);
                this.message = message;
            }
        
            public String getMessage() {
                return message;
            }
        }
        
      • registerListeners方法,将所有的Listener对象注册到广播器中。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NC1S2aP4-1685347461599)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719171504749.png)]

        finishBeanFactoryInitialization方法核心
      • finishBeanFactoryInitialization方法,实例化所有剩余非懒加载的对象[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M2LbjgXF-1685347461599)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719172613735.png)]

        1. 如果bean工厂中包含名为“conversionService”的bean,并且它的类型是ConversionService,则将它设置为bean工厂的转换服务。
        2. 如果bean工厂中没有嵌入式值解析器,则添加一个嵌入式值解析器,用于解析占位符。
        3. 对于所有实现了LoadTimeWeaverAware接口的bean,调用getBean()方法以确保它们已经被实例化。
        4. 设置bean工厂的临时类加载器为null。
        5. 冻结bean工厂的配置,以防止进一步的修改。
        6. 预实例化所有单例bean。

        重点为preInstantiateSingletons方法 他具体使用了反射实例化了bean对象。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x4HsVTXS-1685347461600)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210719172941076.png)]

      ​ 这段代码是 Spring Framework 中的一个方法,用于预先实例化所有的单例 bean。下面是对代码的详细解读和优化建议:

      1. 首先,该方法会记录日志,如果日志级别为 TRACE,则会输出 "Pre-instantiating singletons in " + this。

      2. 接着,该方法会获取所有的 bean 名称,并遍历这些 bean 名称。

      3. 对于每个 bean 名称,该方法会获取对应的 bean 定义,并判断该 bean 是否为抽象类、是否为单例、是否为懒加载。

      4. 如果该 bean 是 FactoryBean,则会获取 FactoryBean 实例,并判断是否需要立即初始化。

      5. 最后,该方法会返回所有的单例 bean 实例。具体实现如下:

        protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
            String beanName = this.transformedBeanName(name);
            Object sharedInstance = this.getSingleton(beanName);
            Object beanInstance;
            if (sharedInstance != null && args == null) {
                if (this.logger.isTraceEnabled()) {
                    if (this.isSingletonCurrentlyInCreation(beanName)) {
                        this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                    } else {
                        this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                    }
                }
        
                beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
            } else {
                if (this.isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }
        
                BeanFactory parentBeanFactory = this.getParentBeanFactory();
                if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                    String nameToLookup = this.originalBeanName(name);
                    if (parentBeanFactory instanceof AbstractBeanFactory) {
                        return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                    }
        
                    if (args != null) {
                        return parentBeanFactory.getBean(nameToLookup, args);
                    }
        
                    if (requiredType != null) {
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
        
                    return parentBeanFactory.getBean(nameToLookup);
                }
        
                if (!typeCheckOnly) {
                    this.markBeanAsCreated(beanName);
                }
        
                StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);
        
                try {
                    if (requiredType != null) {
                        beanCreation.tag("beanType", requiredType::toString);
                    }
        
                    RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                    this.checkMergedBeanDefinition(mbd, beanName, args);
                    String[] dependsOn = mbd.getDependsOn();
                    String[] var12;
                    if (dependsOn != null) {
                        var12 = dependsOn;
                        int var13 = dependsOn.length;
        
                        for(int var14 = 0; var14 < var13; ++var14) {
                            String dep = var12[var14];
                            if (this.isDependent(beanName, dep)) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                            }
        
                            this.registerDependentBean(dep, beanName);
        
                            try {
                                this.getBean(dep);
                            } catch (NoSuchBeanDefinitionException var31) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
                            }
                        }
                    }
        
                    if (mbd.isSingleton()) {
                        sharedInstance = this.getSingleton(beanName, () -> {
                            try {
                                return this.createBean(beanName, mbd, args);
                            } catch (BeansException var5) {
                                this.destroySingleton(beanName);
                                throw var5;
                            }
                        });
                        beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    } else if (mbd.isPrototype()) {
                        var12 = null;
        
                        Object prototypeInstance;
                        try {
                            this.beforePrototypeCreation(beanName);
                            prototypeInstance = this.createBean(beanName, mbd, args);
                        } finally {
                            this.afterPrototypeCreation(beanName);
                        }
        
                        beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                    } else {
                        String scopeName = mbd.getScope();
                        if (!StringUtils.hasLength(scopeName)) {
                            throw new IllegalStateException("No scope name defined for bean ��" + beanName + "'");
                        }
        
                        Scope scope = (Scope)this.scopes.get(scopeName);
                        if (scope == null) {
                            throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                        }
        
                        try {
                            Object scopedInstance = scope.get(beanName, () -> {
                                this.beforePrototypeCreation(beanName);
        
                                Object var4;
                                try {
                                    var4 = this.createBean(beanName, mbd, args);
                                } finally {
                                    this.afterPrototypeCreation(beanName);
                                }
        
                                return var4;
                            });
                            beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                        } catch (IllegalStateException var30) {
                            throw new ScopeNotActiveException(beanName, scopeName, var30);
                        }
                    }
                } catch (BeansException var32) {
                    beanCreation.tag("exception", var32.getClass().toString());
                    beanCreation.tag("message", String.valueOf(var32.getMessage()));
                    this.cleanupAfterBeanCreationFailure(beanName);
                    throw var32;
                } finally {
                    beanCreation.end();
                }
            }
        
            return this.adaptBeanInstance(name, beanInstance, requiredType);
        }
        
      6. 首先,该方法会将 bean 名称转换为规范化的 bean 名称,并尝试从单例缓存中获取 bean 实例。

      7. 如果单例缓存中存在 bean 实例,则直接返回该实例。

      8. 如果单例缓存中不存在 bean 实例,则判断该 bean 是否正在创建中,如果是,则抛出 BeanCurrentlyInCreationException 异常。

      9. 如果存在父级 BeanFactory,并且当前 BeanFactory 中不存在该 bean 的定义,则委托给父级 BeanFactory 进行处理。

      10. 如果需要创建新的 bean 实例,则先标记该 bean 已经被创建,然后开始创建 bean 实例。

      11. 创建 bean 实例时,会先检查该 bean 的依赖关系,如果存在循环依赖,则抛出 BeanCreationException 异常。

      12. 如果该 bean 是单例,则先尝试从单例缓存中获取 bean 实例,如果不存在,则创建新的 bean 实例,并将其放入单例缓存中。

      13. 如果该 bean 是原型,则直接创建新的 bean 实例。

      14. 如果该 bean 是其他作用域,则委托给对应的 Scope 进行处理。

      15. 最后,该方法会将 bean 实例适配为指定类型,并返回该实例。

      protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
      if (this.logger.isTraceEnabled()) {
      this.logger.trace(“Creating instance of bean '” + beanName + “'”);
      }

        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
        
        try {
            mbdToUse.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException var9) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
        }
        
        Object beanInstance;
        try {
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
            if (beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var10) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
        }
        
        try {
            beanInstance = this.doCreateBean(beanName, mbdToUse, args);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
        
            return beanInstance;
        } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
            throw var7;
        } catch (Throwable var8) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
        }
         }
      
      1. 方法签名

    方法签名中的@Nullable注解表示参数args可以为null。

    1. 解析Bean的Class

    首先通过resolveBeanClass方法解析Bean的Class,如果beanClass不为null且不是public的,且mbd中没有设置允许非public访问,则抛出BeanCreationException异常。这里建议在抛出异常时,将异常信息中的beanName和beanClass.getName()打印出来,方便排查问题。

    优化建议:可以在BeanDefinition中增加一个属性,用于标识是否允许非public访问,这样就不需要每次都判断了。

    1. 实例化Bean

    如果mbd中设置了instanceSupplier,则通过该Supplier获取Bean实例;如果mbd中设置了factoryMethodName,则通过该方法实例化Bean;否则,根据构造函数参数的解析情况,选择合适的构造函数实例化Bean。

    优化建议:可以在BeanDefinition中增加一个属性,用于标识是否使用构造函数实例化Bean,这样就不需要每次都判断了。

    1. 解析构造函数

    如果构造函数参数已经解析过,则直接根据是否需要自动装配来选择合适的构造函数实例化Bean;否则,通过BeanPostProcessor解析构造函数,如果没有找到合适的构造函数,则根据mbd中的信息选择合适的构造函数实例化Bean。

    优化建议:可以在BeanDefinition中增加一个属性,用于缓存已经解析过的构造函数,这样就不需要每次都重新解析了。

    1. 返回BeanWrapper

    最后返回一个BeanWrapper对象,该对象包装了实例化的Bean对象和Bean的元数据信息。

    最终通过反射生成对应的bean对象。

     public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner, @Nullable Object factoryBean, Method factoryMethod, Object... args) {
            try {
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged(() -> {
                        ReflectionUtils.makeAccessible(factoryMethod);
                        return null;
                    });
                } else {
                    ReflectionUtils.makeAccessible(factoryMethod);
                }
    
                Method priorInvokedFactoryMethod = (Method)currentlyInvokedFactoryMethod.get();
    
                Object var9;
                try {
                    currentlyInvokedFactoryMethod.set(factoryMethod);
                    Object result = factoryMethod.invoke(factoryBean, args);
                    if (result == null) {
                        result = new NullBean();
                    }
    
                    var9 = result;
                } finally {
                    if (priorInvokedFactoryMethod != null) {
                        currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
                    } else {
                        currentlyInvokedFactoryMethod.remove();
                    }
    
                }
    
                return var9;
            } catch (IllegalArgumentException var16) {
                throw new BeanInstantiationException(factoryMethod, "Illegal arguments to factory method '" + factoryMethod.getName() + "'; args: " + StringUtils.arrayToCommaDelimitedString(args), var16);
            } catch (IllegalAccessException var17) {
                throw new BeanInstantiationException(factoryMethod, "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", var17);
            } catch (InvocationTargetException var18) {
                String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
                if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory && ((ConfigurableBeanFactory)owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
                    msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider declaring the factory method as static for independence from its containing instance. " + msg;
                }
    
                throw new BeanInstantiationException(factoryMethod, msg, var18.getTargetException());
            }
        }
    }
    

    这段代码是 Spring Framework 中的一个方法,用于实例化一个 Bean。具体来说,它会调用一个工厂方法(factoryMethod)来创建一个对象,并返回该对象的实例。

    下面是对代码的详细解读:

    1. 首先,该方法会尝试通过反射调用 factoryMethod 方法来创建一个对象。factoryMethod 方法通常是一个静态方法或者是一个实例方法,它会返回一个对象实例。
    2. 在调用 factoryMethod 方法之前,该方法会使用 ReflectionUtils.makeAccessible() 方法来确保 factoryMethod 方法是可访问的。这是因为 factoryMethod 方法可能是一个私有方法,需要使用 ReflectionUtils.makeAccessible() 方法来打开访问权限。
    3. 在调用 factoryMethod 方法之前,该方法会将当前正在调用的工厂方法设置为 factoryMethod。这是为了在发生异常时能够正确地恢复当前正在调用的工厂方法。
    4. 如果 factoryMethod 方法返回 null,则该方法会创建一个 NullBean 对象并返回。
    5. 在调用 factoryMethod 方法之后,该方法会将当前正在调用的工厂方法恢复为之前的值。
    6. 如果 factoryMethod 方法抛出异常,则该方法会根据异常类型抛出相应的异常。如果是 IllegalArgumentException,则会抛出 BeanInstantiationException 异常,并将异常信息设置为“Illegal arguments to factory method ‘factoryMethod.getName()’; args: args”。如果是 IllegalAccessException,则会抛出 BeanInstantiationException 异常,并将异常信息设置为“Cannot access factory method ‘factoryMethod.getName()’; is it public?”。如果是 InvocationTargetException,则会抛出 BeanInstantiationException 异常,并将异常信息设置为“Factory method ‘factoryMethod.getName()’ threw exception”。
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
    
        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }
    
        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }
    
        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }
    
                mbd.postProcessed = true;
            }
        }
    
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }
    
            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }
    
        Object exposedObject = bean;
    
        try {
            this.populateBean(beanName, mbd, instanceWrapper);
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }
    
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }
    
        if (earlySingletonExposure) {
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;
    
                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
    
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }
    
        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }
    
    • finishBeanFactoryInitialization

      此方法是

      protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
          if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
              beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
          }
      
          if (!beanFactory.hasEmbeddedValueResolver()) {
              beanFactory.addEmbeddedValueResolver((strVal) -> {
                  return this.getEnvironment().resolvePlaceholders(strVal);
              });
          }
      
          String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
          String[] var3 = weaverAwareNames;
          int var4 = weaverAwareNames.length;
      
          for(int var5 = 0; var5 < var4; ++var5) {
              String weaverAwareName = var3[var5];
              this.getBean(weaverAwareName);
          }
      
          beanFactory.setTempClassLoader((ClassLoader)null);
          beanFactory.freezeConfiguration();
          beanFactory.preInstantiateSingletons();
      }
      
      • 完成实例化之后对属性赋初始值与调用Aware方法。

循环依赖

什么是循环依赖

  • 循环依赖是指:循环依赖就是循环引用,就是两个或多个bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环。此处不是循环调用,循环调用是方法之间的环调用

  • 如:Bean A的属性中含有Bean B,Bean B的属性中含有Bean A 。这样,在对象实例化之后填充属性时,会循环的注入彼此的对象。

    怎么解决循环依赖

    使用三级缓存,既三个map容器。

  • 三级缓存的名称和分别储存的内容

    • 一级缓存singletonObjects,存放成品对象,既完整以Bean对象(已实例化,已初识化)
    • 二级缓存earlySingletonObjects,存放半成品对象(已实例化,未初始化)
    • 三级缓存singletonFactories,存放lambda表达式,来完成代理对象的覆盖过程
  • 三级缓存的查找顺序

    一、二、三级依次查询[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-flNwYuiB-1685347461600)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210724162847387.png)]

    以A注入B,B注入A为例:

    A属性注入前就把lambda表达式放入了第三级缓存,所以B再注入A的时候会从第三级缓存中找到A的lambda表达式并执行,然后将半成品Bean放入第二级缓存,所以此时B注入的只是半成品的A对象,B创建完成后返回给A注入,A继续初始化,完成创建。

    在这里插入图片描述

    注意: B注入的半成品A对象只是一个引用,所以之后A初始化完成后,B这个注入的A就随之变成了完整的A

    使用三级缓存解决循环依赖的过程

    • 思想:创建对象时将实例化和初始化分开处理,提前暴露对象。

      图解:以Bean A、Bean B相互将对方作为自己的属性为例

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o1gIPkrh-1685347461600)(C:\Users\Ric\AppData\Roaming\Typora\typora-user-images\image-20210724161652939.png)]

Spring扩展机制

  • 利用BeanPostProcessor和BeanFactoryPostProcessor

    • 一、利用后置处理器扩展Spring容器
      Bean后置处理器(BeanPostProcessor 接口)
      如果希望在Spring容器完成实例化、配置和初始化bean之后实现某些自定义逻辑, 则可以实现一个或多个 BeanPostProcessor 接口。BeanPostProcessor中有两个抽象方法:

      postProcessBeforeInitialization方法:在初始化方法(InitializingBean的afterPropertiesSet、init-method指定的方法等)之前调用
      postProcessAfterInitialization方法:在初始化方法(InitializingBean的afterPropertiesSet、init-method指定的方法等)之后调用

    • 二、ApplicationListener
      监听容器发布的事件,实现一个监听器的步骤:

      1、编写一个监听器(实现ApplicationListener类)来监听某个事件(ApplicationEvent极其子类)
      2、把监听器加入到容器中
      3、只要容器中有相关事件发布,就能监听到这个事件
      ContextRefreshedEvent : 容器刷新完成(所有bean都完成创建)会发布这个事件
      ContextClosedEvent : 关闭容器会发布这个事件
      4、手动发布一个事件:applicationContext.publishEvent()

      @Component
      public class MyApplicationListener implements ApplicationListener{

      //当容器中发布此事件,方法会得到触发
      @Override
      public void onApplicationEvent(ApplicationEvent event) {
          System.out.println("收到事件:"+event);   
      }
      
    • 三、获取容器底层组件(各种Aware)
      自定义组件想要使用Spring容器底层的一些组件(ApplicationContext, Environment,BeanFactory等),自定义组件需要实现XXXAware接口(继承Aware接口),在创建对象的时候,Spring会调用接口规定的方法注解相关组件,把Spring底层的一些组件注入到自定义的Bean中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/584590.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

房产中介APP开发功能有哪些?

房产中介APP开发功能有哪些&#xff1f; 1. 发布信息。中介或房东通过房地产中介APP客户端发布出租房屋的相关信息。 2. 房屋搜查。根据不同类型的房源进行分类&#xff0c;如公寓、整租、合租、写字楼、办公楼等&#xff0c;也可以根据不同的位置信息、商圈、距…

2023年下半年软考高级需要报班吗?

首先&#xff0c;对于软考高级考试报班与否的问题&#xff0c;需要根据自身的情况来做出决定。如果你有较强的自学能力&#xff0c;且具备丰富的实际工作经验和技术知识&#xff0c;那么不报班也完全可以自学备考。但如果你对软件工程的知识掌握程度较低&#xff0c;或者时间紧…

算法01-算法概念与描述

文章目录 总结大纲要求算法概念举个例子&#xff1a;量水问题 算法描述算法的时间复杂度 总结 本系列为C算法学习系列&#xff0c;会介绍 算法概念与描述&#xff0c;入门算法&#xff0c;基础算法&#xff0c;数值处理算法&#xff0c;排序算法&#xff0c;搜索算法&#xff…

软件测试炸了,作为从业者,你做好准备了吗?

软件测试行业已经发生很大变化&#xff0c;你跟上变化了吗&#xff1f; 岗位少不可怕&#xff0c;要求越来越高也不可怕&#xff0c;可怕的是&#xff0c;软件测试行业已经发生巨变&#xff0c;而你却原地踏步&#xff01;目前一线大厂更多倾向于招收测试开发&#xff0c;或者…

06. 数据结构之散列表

前言 散列表也叫作哈希表&#xff08;hash table&#xff09;&#xff0c;这种数据结构提供了键&#xff08;Key&#xff09;和值&#xff08;Value&#xff09;的映射关系。只要给出一个Key&#xff0c;就可以高效查找到它所匹配的Value&#xff0c;时间复杂度接近于O(1) 1.…

photoshop矫正扫描图片的倾斜问题以及修改图片内容

由于工程原因&#xff0c;资料需要重新梳理 1.扫描工程表格到电脑中 2.在ps中导入表格内容&#xff08;表格有时候是倾斜的&#xff09; 需要修正为正常状态&#xff0c;即垂直状态 设置步骤&#xff1a; 1.调整ps的背景颜色与所在图片的背景颜色一致 用吸管工具&#xff…

AbandonedConnectionCleanupThread$ConnectionFinalizerPhantomReference内存溢出

网上查了查资料&#xff0c;根据自己情况在这里整理了一下&#xff0c;供大家学习和参考。 目录 1、现象 2、mysql-connector-java 源码分析 3、解决方法 3.1、配置disableAbandonedConnectionCleanup 3.2、暴力解决方式-----定时GC 4、什么是虚引用 5、关联对象真的被回…

数据可视化:趋势类可视化图表大全

图表是处理数据的重要组成部分&#xff0c;因为它们是一种将大量数据压缩为易于理解的格式的方法。数据可视化可以让受众快速Get到重点。 数据可视化的图表类型极其丰富多样&#xff0c;而且每种都有不同的用例&#xff0c;通常&#xff0c;创建数据可视化最困难的部分是确定哪…

【Linux】常用命令的汇总学习

文章目录 1.目录切换命令2.目录操作命令3.把ls -l中包含字母file&#xff08;不区分大小写&#xff09;的内容输出4.统计txt中的某个字符串5.grep命令的使用6.linux查找当前目录下所有txt文件7.linux中的find命令8.查看系统所有的进程信息9.如何确定文件的类型10.tar解压缩11.U…

员工防范网络钓鱼攻击的10个实用技巧

你知道网络钓鱼攻击的危害吗&#xff1f;以下是网络钓鱼的定义及其引起关注的原因&#xff1a; Verizon 最近的一份报告显示&#xff0c;82&#xff05;的网络漏洞均由人为因素造成&#xff0c;比如窃取凭证、网络钓鱼攻击、社会工程学、冒名顶替、滥用或错误等。网络钓鱼攻击…

惊!掌握千问通义的关键,从这些必知内容开始!

今年快过半了&#xff0c;要说顶流话题还得是ChatGPT&#xff0c;相关话题的热度居高不下&#xff0c;而其从GPT-3.5到GPT-4的升级&#xff0c;也让我们深刻了解了什么叫一代版本一代神&#xff0c;从GPT-3.5到GPT-4&#xff0c;真的就是一个跨阶级式的升级。 技术内涵 ChatGPT…

某SRC的渗透测试实战

前言 因为不甘心被称作会只点鼠标的猴子&#xff0c;所以开始了一次某SRC漏洞挖掘&#xff0c;为期一个多星期。文章有点长&#xff0c;但请耐心看完&#xff0c;记录了完整的SRC漏洞挖掘实战 渗透过程 因为选择的幸运儿没有对测试范围进行规划&#xff0c;所以此次范围就是…

OPC UA客户端访问 OPC DA服务器

目标 用OPC UA客户端&#xff08;如UaExpert&#xff09;读取OPC DA服务器上的点。 原理 OPC DA是基于COM/DCOM的&#xff0c;传统OPC DA客户端访问非本机OPC DA服务时需要配置DCOM。OPC UA客户端无法直接访问 OPC DA服务&#xff0c;需要将OPC DA服务映射为OPC UA服务&#x…

【Excel技巧】3个限制权限,保护表格不被人随意改动

Excel表格是很多人工作中经常用到的办公软件&#xff0c;有时候做好表格发给对方后&#xff0c;总是担心会被不小心做了改动。 如果有这种顾虑&#xff0c;就一定要用上Excel表格的3个“限制权限”&#xff0c;可以根据不同的情况&#xff0c;设置不同保护。下面就来看看可以设…

LAMP配置安装

目录 一&#xff1a;LAMP 1、(平台)Linux 2、(前台)Apache 3、(后台)MySQL 4、(中间连接)PHP/Perl/Python 5. Lamp工作原理 二&#xff1a;编译安装Apache httpd服务 1.关闭防火墙&#xff0c;将安装Apache所需软件包传到/opt目录下 2.安装环境依赖包 3.配置软件模块…

打造繁荣社区:Solaris 与 Web3 合作的力量

在去中心化金融&#xff08;DeFi&#xff09;的动态格局中&#xff0c;Solaris 作为一股开创性力量涌现&#xff0c;为衍生品提供了强大的 Web3 基础设施。Solaris 成功的关键在于其充满活力且迅速增长的社区&#xff0c;该社区在塑造平台影响力和促进创新方面发挥着关键作用。…

C++ 新特性

1.auto、decltype 用于自动推断类型 2.自动追踪返回值类型 3. 列表初始化和列表方式类型收窄 //列表初始化 vector<int>res{1,2,3,4,5}; //防止类型收窄 int a 1024; char b a;//可以执行 char b{a};//报错 4.基于范围的for循环 vector<int>res{1,2,3,4}; fo…

“外行转网工,我只用了三个月”

大家好&#xff0c;我是老杨。 在这行发展了这么多年&#xff0c;经常会有人来问我&#xff0c;网工该怎么提升自己&#xff0c;又或是怎么入行。 其实这事儿不难想&#xff0c;技术工种最需要做的是什么&#xff0c;自然是提升技术。 而技术提升&#xff0c;途径也只有学习…

k维空间中的超平面的维度是多少?

超平面中的任何点 x x x可以用一个法向量 w w w和超平面上的一个点 x 0 x_0 x0​表示. x x x可以用 w w w和 x 0 x_0 x0​表示&#xff1a; ( x − x 0 ) ⋅ w 0 w T x − w T x 0 0 w T x b 0 \begin{split} (x-x_0) \cdot w &0 \\ w^Tx-w^Tx_0 &0 \\ w^Txb &a…

高压断路器工作运行要求是什么

1、断路器应在规定的技术参数范围内运行。 2、断路器必须配备可靠的操作电源和合闸电源。 3、送电应先合刀闸后合断路器&#xff1b;停电先断开断路器&#xff0c;检查确已断开后再拉刀闸。 4、110kV高压设备的巡视检查可由一人进行&#xff0c;但距带电体的距离应不小于1.5…