spring

一、refresh

debug模式,跟踪 SpringApplication.run() 启动方法,进入SpringApplication类,发现调用其refresh方法,该方法调用AbstractApplicationContext类的 refresh()。

忘记出处了,想起来补上

public abstract class AbstractApplicationContext extends DefaultResourceLoader
    implements ConfigurableApplicationContext {
    @Override
    public void refresh() throws BeansException, IllegalStateException {
     // 给容器refresh加锁,避免容器处在refresh阶段,容器进行了初始化或销毁的操作 
synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 准备刷新上下文。(为刷新准备此上下文,设置其启动日期和活动标志以及执行属性源的任何初始化。) prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // 告诉子类刷新内部 bean 工厂。(之前的beanFactory如果存在的话则关闭,然后创建新的beanFactory
       // 调用refreshBeanFactory()
       //   1、创建了 DefaultListableBeanFactory 对象 -- 创建BeanFactory用来操作Bean:存储Bean的定义信息,实例化Bean、填充属性、初始化Bean、完整Bean、销毁Bean
       //  2、customizeBeanFactory(beanFactory); -- 自定义BeanFactory
       // 3、loadBeanDefinitions(beanFactory); -- 加载bean的定义信息
       //    设置 Environment -- 环境变量和系统变量ResourceLoaderBeanDefinitionReader -- 读取Bean定义信息、[BeanDefinitionRegistry、EntityResolver]等
        
       // 4、synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory;}。
                   -- refreshBeanFactory()其后的getBeanFactory()会获取这个beanFactory。beanFactory是线程共享的,为了保证线程安全所以加上对象锁。
       //             其声明:private final Object beanFactoryMonitor = new Object();
       //
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 准备在此上下文中使用的 bean 工厂。(配置工厂的标准上下文特性,例如上下文的类加载器和后处理器) prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 允许在上下文子类中对 bean 工厂进行后处理。(扩展用的:其他框架或第三方插件重写使用) postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 调用在上下文中注册为 bean 的工厂处理器。(实例化并调用所有已注册的 BeanFactoryPostProcessor bean,如果给定顺序,按显式顺序。) invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 注册拦截 bean 创建的 bean 处理器。 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // 初始化此上下文的消息源。(国际化配置) initMessageSource(); // Initialize event multicaster for this context. // 为此上下文初始化事件多播器。 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 初始化特定上下文子类中的其他特殊 bean。(扩展用的) onRefresh(); // Check for listener beans and register them. // 检查侦听器 bean 并注册它们。 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. // 实例化所有剩余的(非懒加载)单例。 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // 最后一步:发布对应的事件。 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. // 销毁已经创建的单例以避免悬空资源。 destroyBeans(); // Reset 'active' flag. // 重置“活动”标志。 cancelRefresh(ex); // Propagate exception to caller. // 将异常传播给调用者。 throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... // 重置 Spring 核心中的常见内省缓存,因为我们 // 可能不再需要单例 bean 的元数据... resetCommonCaches(); } } } }

参考:https://www.cnblogs.com/lemon-flm/p/7551744.html 多线程同步问题。

二、DefaultListableBeanFactor (转载:https://www.cnblogs.com/duanxz/p/5426638.html)  

1. DefaultListableBeanFactory的作用

默认实现了ListableBeanFactory和BeanDefinitionRegistry接口,基于bean definition对象,是一个成熟的bean factroy。

最典型的应用是:在访问bean前,先注册所有的definition(可能从bean definition配置文件中)。使用预先建立的bean定义元数据对象,从本地的bean definition表中查询bean definition因而将不会花费太多成本。

DefaultListableBeanFactory既可以作为一个单独的beanFactory,也可以作为自定义beanFactory的父类。

注意:特定格式bean definition的解析器可以自己实现,也可以使用原有的解析器,如:

PropertiesBeanDefinitionReader和XmLBeanDefinitionReader。

2. DefaultListableBeanFactory的继承关系

以下出处:https://blog.csdn.net/Taylar_where/article/details/90547570

3.DeafultListableBeanFactory所实现的接口及接口作用:

AliasRegistry:  AliasRegistry是制定别名的管理规则,定义了对alias的简单的简单增改删等操作。

SimpleAlliasRegistry:  主要是用map作为alias的缓存,并对接口AliasRegistry进行实现。

SingletonBeanRegistry:  定义对单例的注册及获取。

BeanFactory:  定义获取bean及bean的各种属性

DefaultSingletonBeanRegistry:  对接口SingletonBeanRegistry各函数的实现。

HierarchicalBeanFactory:  继承BeanFactory,也就是在BeanFactory的基础上定义了对parentFactory的支持。

BeanDefinitionRegistry:  定义对BeanDefinition的各种增改删操作。BeanDefinition中定义的属性有诸如类名、sccope、属性、构造函数参数列表、依赖的bean、是否单例类、
    是否懒加载等,其实就是将Bean的定义信息存储到这个BeanDefinition相应的属性中,之后对Bean的操作就是直接对BeanDefinition进行的。 FactoryBeanRegistrySupport: 在DefaultSingletonBeanRegistry基础上增加了对FactoryBean的特殊处理功能。 ConfigurableBeanFactory: 提供配置Factory的各种方法。 ListableBeanFactory: 根据各种条件获得bean的配置清单。 AbstractBeanFactory: 综合FactoryBeanRegistrySupport和ConfigurableBeanFactory的功能。 AutowireCapableBeanFactory: 提供创建bean自动注入,初始化以及应用bean的后置处理器 AbstractAutowireCapableBeanFactory: 综合AbstractBeanFactory并对接口Autowire,CapableBeanFactory进行实现。 ConfigurableListableBeanFactory: BeanFactory配置清单,指定忽略类型及接口等。 而我们的核心类DefaultListableBeanFactory就是综合了上面所有的功能,主要负责了Bean注册后的处理。


层次结构

DefaultListableBeanFactory继承了AbstractAutowireCapalbeBeanFactory以及实现了BeanDefinitionRegistry,ConfigurableListableBeanFactory接口,是Spring注册及加载bean的默认实现。


4.DefaultListableBeanFactory一些常用方法:

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
                                                    Set<String> autowiredBeanNames, TypeConverter typeConverter)

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons,
                                                    boolean allowEagerInit)

在Spring中,凡是以do开头的方法一般都是细节上的逻辑处理,也就是具体的实现代码。

关于doResolveDependency实现的具体逻辑

a.首先将 beanName 和 requiredType 作为参数,并尝试从 BeanFactory 中获取与此对于的 bean。若获取成功,就可以提前结束 doResolveDependency 的逻辑。

b.处理 @value 注解

c.解析数组、List、Map 等类型的依赖,如果解析结果不为空,则返回结果

d.根据类型查找合适的候选项

e.如果候选项的数量为0,则抛出异常。为1,直接从候选列表中取出即可。若候选项数量 > 1,则在多个候选项中确定最优候选项,若无法确定则抛出异常

f.若候选项是 Class 类型,表明候选项还没实例化,此时通过 BeanFactory.getBean 方法对其进行实例化。若候选项是非 Class 类型,则表明已经完成了实例化,此时直接返回即可。

以上出处:https://blog.csdn.net/Taylar_where/article/details/90547570

三、finishBeanFactoryInitialization 详解 https://blog.csdn.net/qq_44836294/article/details/107795639

 简单流程:通过反射实例化Bean --> 填充属性 -->  初始化 --> 完整Bean

中间会产生循环依赖问题:使用三级缓存解决

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    ...
    // 从上至下 分表代表这“三级缓存”
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); //一级缓存
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 二级缓存
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 三级缓存
    ...
    
    /** Names of beans that are currently in creation. */
    // 这个缓存也十分重要:它表示bean创建过程中都会在里面呆着~
    // 它在Bean开始创建时放值,创建完成时会将其移出~
    private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
 
    /** Names of beans that have already been created at least once. */
    // 当这个Bean被创建完成后,会标记为这个 注意:这里是set集合 不会重复
    // 至少被创建了一次的  都会放进这里~~~~
    private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
}

注:AbstractBeanFactory继承自DefaultSingletonBeanRegistry

  • singletonObjects:用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
  • earlySingletonObjects:提前曝光的单例对象的cache,存放原始的 bean 对象(尚未填充属性),用于解决循环依赖
  • singletonFactories:单例对象工厂的cache,存放 bean 工厂对象,用于解决循环依赖
出处:https://blog.csdn.net/fedorafrog/article/details/104550165

 

posted @ 2021-06-15 18:08  暗夜消辰  阅读(55)  评论(0编辑  收藏  举报