zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    font-weight(字体粗细)属性
    Node.js入门(三)
    js难点问题
    Node.js入门(二)
    Node.js入门(一)
    Reactjs的Controller View模式
    智能社的邀请码
    react native 学习资料汇总
    jquery操作select
    分享
  • 原文地址:https://www.cnblogs.com/day1day1up/p/14883004.html
Copyright © 2011-2022 走看看