死磕Spring

2019-02-27  本文已影响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。

上一篇下一篇

猜你喜欢

热点阅读