美文网首页
死磕Spring

死磕Spring

作者: 特仑苏纯牛乳 | 来源:发表于2019-02-27 22:18 被阅读0次

    目标完成对Spring体系的全面深入深深入 透彻理解 输出培训

    第一天 0226

    确立了两条主线
    1.源码 http://cmsblogs.com/?tag=spring%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90
    2.书《Spring实战》《Spring源码》
    完成了对spring IoC,AOP,模板消除样板式代码的深入理解
    Spring IoC五大体系:1.Resource体系,对资源的抽象和访问策略的定义 2.BeanFactory 体系 3.BeanDefinition 体系 4.BeanDefinitionReader 体系 5.ApplicationContext 体系

    第二天 0227

    Resource体系 统一资源加载策略
    Bean装配的自动装配、Java配置、XML配置

    第三天 0228##

    Bean的高级装配……
    beanDefinition


    image.png

    第四天 0301##

    我知道有个人在看,不知道昨天没有更新有没有不开心
    面向切面的spring AspectJ的重要性
    Spring解析XMl具体标签的方式

    第五天 0304##

    bean的加载
    "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 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."

    第六天 0305##

    在死磕bean加载过程源码

    第七天 0306##

    在死磕bean加载过程源码 循环依赖的解决

    第八天 0310##

    各种原因被打断了几天,今天好好看看
    有点难啃 没有啃完 感觉见到曙光了

    第九天 0311##

    createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) 方法,用于实例化 Bean 对象。它会根据不同情况,选择不同的实例化策略来完成 Bean 的初始化,主要包括:

    Supplier 回调:#obtainFromSupplier(final String beanName, final RootBeanDefinition mbd) 方法。
    工厂方法初始化:#instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) 方法。
    构造函数自动注入初始化:#autowireConstructor(final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) 方法。
    默认构造函数注入:#instantiateBean(final String beanName, final RootBeanDefinition mbd) 方法。

    远比我想想的复杂难懂的多……不是谁都可以随随便便的做出精品的……认真的研读的时候,你会发现死磕这两个字 真他妈真切

    第十天0312##

    很高兴 我今天完成了第一个阶段的学习:总结以下问题:
    1.单例模式在解决循环依赖的时候为什么要采用三级缓存,第三级缓存采用ObjectFactory的方式是为了解决什么问题?

    /** Cache of singleton factories: bean name to ObjectFactory.
         *
         * 存放的是 ObjectFactory,可以理解为创建单例 bean 的 factory,对应关系是 bean name --> ObjectFactory
         *
         */
        private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    final Object bean = instanceWrapper.getWrappedInstance();
    // 提前将创建的 bean 实例的工厂 加入到 singletonFactories (三级缓存)中
                // 这里是为了后期避免循环依赖
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    
    /**
         * Add the given singleton factory for building the specified singleton
         * if necessary.
         * <p>To be called for eager registration of singletons, e.g. to be able to
         * resolve circular references.
         * @param beanName the name of the bean
         * @param singletonFactory the factory for the singleton object
         */
        protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
            Assert.notNull(singletonFactory, "Singleton factory must not be null");
            synchronized (this.singletonObjects) {
                if (!this.singletonObjects.containsKey(beanName)) {
                    this.singletonFactories.put(beanName, singletonFactory);
                    this.earlySingletonObjects.remove(beanName);
                    this.registeredSingletons.add(beanName);
                }
            }
        }
    
    /**
         * Obtain a reference for early access to the specified bean,
         * typically for the purpose of resolving a circular reference.
         * @param beanName the name of the bean (for error handling purposes)
         * @param mbd the merged bean definition for the bean
         * @param bean the raw bean instance
         * @return the object to expose as bean reference
         */
        protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
            Object exposedObject = bean;
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                        exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                    }
                }
            }
            return exposedObject;
        }
    

    2.第二级缓存返回的是否为BeanWrapper,这个BeanWrapper是什么概念?

        /** Cache of early singleton objects: bean name to bean instance.
         *
         * 存放的是早期的 bean,对应关系也是 bean name --> bean instance。
         * 它与 singletonObjects 区别在于 earlySingletonObjects 中存放的 bean 不一定是完整的,
         * 从上面过程中我们可以了解,bean 在创建过程中就已经加入到 earlySingletonObjects 中了,
         * 所以当在 bean 的创建过程中就可以通过 getBean() 方法获取。
         *
         * 这个 Map 也是解决【循环依赖】的关键所在。
         *
         */
        private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    

    一级缓存:

        /** Cache of singleton objects: bean name to bean instance.
         *  存放的是单例 bean 的映射。
         *  对应关系为 bean name --> bean instance
         */
        private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    

    第一个问题中提到的,程序首先尝试从一级缓存“singletonObjects”中获取实例(这里面获取的实例实际上是已经创建完成的实例),如果获取不到,这尝试冲二级缓存“earlySingletonObjects”中获取(这里存放的是未完成创建的BeanWrapper),如果仍然获取不到,则尝试从三级缓存“singletonFactories”中获取一个ObjectFactory然后调用这个ObjectFactory的getObject方法来创建bean,并放到二级缓存中,并将ObjectFactory从三级缓存中remove掉。

    3.怎样深度理解这三个过程a.实例化(createBeanInstance)b.填充属性(popularBean)c.初始化(initializeBean)?
    4.getObjectForBeanInstance()的作用
    5.aware的使用场景及具体实现
    6.post-process的使用场景及具体实现
    7.createBeanWrapper的supplier回调实现方式
    8.怎样保证了线程安全的单例Bean
    在bean创建的时候首先将bean注册到 DefaultSingletonBeanRegistry
    /** Names of beans currently excluded from in creation checks. */
    private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    中;
    依赖Bean在进行getObjectFromFactoryBean 中的 object = doGetObjectFromFactoryBean(factory, beanName);操作时,使用了FactoryBean的指定方法
    我预计在完成framwork前 来详细解答这8个问题

    近来的spring研究让我有一点点小兴奋

    第11天0313##

    今天好累
    大体整理一下思路接下来需要完成springFramework的整体深度架构到细节的研究---->然后是web部分springmvc---->然后是springBoot---->然后是springCloud、springDataFlow;计划于4.30前全部完成

    12 0314##

    LoadTimeWeaverAware:加载Spring Bean时织入第三方模块,如AspectJ
    BeanClassLoaderAware:加载Spring Bean的类加载器
    BootstrapContextAware:资源适配器BootstrapContext,如JCA,CCI
    ResourceLoaderAware:底层访问资源的加载器
    BeanFactoryAware:声明BeanFactory
    PortletConfigAware:PortletConfig
    PortletContextAware:PortletContext
    ServletConfigAware:ServletConfig
    ServletContextAware:ServletContext
    MessageSourceAware:国际化
    ApplicationEventPublisherAware:应用事件
    NotificationPublisherAware:JMX通知
    BeanNameAware:声明Spring Bean的名字

    我们始终需要注意的是 BeanFactoryPostProcessor 是与 BeanDefinition 打交道的,如果想要与 Bean 打交道,请使用 BeanPostProcessor 。

    12 0315##

    Bean 的转换过程


    image.png

    ApplicationContext 的架构图


    image.png
    load BeanDefinition 的全流程
    image.png

    get Bean 的全流程


    image.png

    接下来我将用两天时间系统梳理一下
    下周一3.18 我将召开小组技术讨论会,深入讨论一些深度细节问题

    13 0316##

    日本旅行刷新认知

    14 0326##

    回归死磕源码系列

    15 0330##

    回答8个核心问题

    写在最后,完成我的第一个阶段的笔记:
    一句话总结spring解决循环依赖的问题:通过spring容器,提前暴露刚完成构造器注入,但是未完成其他步骤(不如setter注入)的bean来完成的,而且只能解决单例bean作用域的bean循环依赖。通过提前暴露一个工程方法从而使其他bean能够引用到该bean。

    相关文章

      网友评论

          本文标题:死磕Spring

          本文链接:https://www.haomeiwen.com/subject/jtiquqtx.html