目标完成对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。
网友评论