Spring IOC(三)单例 bean 的注册管理

Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)

在 Spring 中 Bean 有单例和多例之分,只有单例的 bean 才会被 BeanFactory 管理,这个工作就是由 SingletonBeanRegistry 完成的。

public interface SingletonBeanRegistry {
void registerSingleton(String beanName, Object singletonObject);
Object getSingleton(String beanName); boolean containsSingleton(String beanName);
String[] getSingletonNames();
int getSingletonCount(); // 暴露所有的 singletonObjects 给外部
Object getSingletonMutex();
}

SingletonBeanRegistry 的默认实现为 DefaultSingletonBeanRegistry,主要功能如下:

  1. 单例 bean 的注册和查找。
  2. 扩展了 SingletonBeanRegistry 的功能,还管理 bean 的生命周期,包括 bean 的创建和销毁。与 bean 生命周期有关的方法如下:
// 1. 创建 bean。先从缓存中获取 bean,allowEarlyReference=true 时会尝试从 singletonFactories 获取提暴露的 bean
// 缓存中没有就调用 singletonFactory 方法创建 bean
public Object getSingleton(String beanName);
protected Object getSingleton(String beanName, boolean allowEarlyReference)
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory); // 2. 销毁 bean。可以销毁全部的 bean,也可以销毁指定的 bean,最终都是调用 destroyBean 完成的。
// 销毁 bean 之前需要先销毁依赖它的所有 bean,再调用 bean.destroy() 销毁自己
public void destroySingletons();
public void destroySingleton(String beanName);
protected void destroyBean(String beanName, @Nullable DisposableBean bean);

一、相关属性

(1) 与单例对象保存有关的四个集合

我们先从下面四个和单例有关的集合说起。前三个集合和 bean 的创建有关,其中 singletonObjects 保存已经创建成功的 bean 的集合,singletonFactories 和 earlySingletonObjects 属于中间过程,一旦 bean 创建成功就会删除对应的记录,用于解决 bean 属性注入过程中的循环依赖的问题。最后一个用来保存当前所有已注册的 bean。

// 1.1 保存最终创建成功的单例 beanName -> beanInstance
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 1.2 中间变量,beanName -> Objectfactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 1.3 中间变量,bean 还在创建的时候就可以获取,用于检测循环引用
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 2. 用来保存当前所有已注册的 bean
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

这里涉及用于存储 bean 的不同的 Map,可能让人感到崩溃,简单解释如下:

  1. singletonObjects:用于保存 beanName 和创建 bean 实例之间的关系,beanName -> beanInstance
  2. singletonfactories:用于保存 beanname 和创建 bean 的工厂之间的关系,beanName -> Objectfactory
  3. earlySingletonObjects:也是保存 beanName 和创建 bean 实例之间的关系,与 singletonObjects 的不同之处在于,当一个单例 bean 被放到这里面后,那么当 bean 还在创建过程中,就可以通过 getBean 方法获取到了,其目的是用来检测循环引用。
  4. registeredsingletons:用来保存当前所有已注册的 bean

(2) 与单例对象创建有关的几个属性

// 1. 保存正在创建的 bean
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 2. 保存已经创建的 bean 集合,这样进行依赖循环检查时
// 如果已经 bean 在 inCreationCheckExclusions 中了,就不用再检查 singletonsCurrentlyInCreation 了
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 3. 保存 bean 创建过程时的异常
private Set<Exception> suppressedExceptions;

(3) 与单例对象销毁有关的四个集合

// 1. 一旦调用 destroySingletons() 销毁所有的 bean 时就修改为 true
private boolean singletonsCurrentlyInDestruction = false; // 2. 下面四个集合都和 bean 的销毁有关
// 2.1 保存每个 bean 的 destroy 方法
private final Map<String, Object> disposableBeans = new LinkedHashMap<>(); // 3.1 保存当前 bean 内的所有 bean 信息。containingBean -> containedBean
// 当注册 containedBeanMap 的同时也会注册 dependentBeanMap 和 dependenciesForBeanMap
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16); // 3.2 保存依赖这个 bean 的所有 bean 的集合,依赖我的。containedBean -> containingBean
// 所以销毁这个 bean 的同时也要销毁依赖它的所有 bean
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
// 3.3 保存当前 bean 依赖的所有 bean 的集合,我依赖的。containingBean -> containedBean
// 所以销毁这个 bean 只要清空对应的记录即可,而不会销毁该 bean 依赖的其它 bean
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

二、bean 的注册与删除

@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
synchronized (this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException();
}
addSingleton(beanName, singletonObject);
}
} // 这个方法只有在本类中才调用,bean 属性注入完成,直接添加 singletonObject
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
} // AbstractAutowireCapableBeanFactory#doCreateBean 调用。注册 singletonFactory
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}

这个没什么可说的,主要是要理清这四个集合的功能。可以看到有两种方法注册单例,这两种情况都会将 bean 注册到 registeredSingletons 中:

  • 一是 bean 创建完成直接注册 singletonObjects。此时 bean 已经创建完成,直接注册到 singletonObjects 集合中,同时清理创建过程中所记录的各种辅助状态。
  • 二是 bean 创建开始前先注册其引用对象 singletonFactory。此时先注册到 singletonFactories 中,通过 allowEarlyReference=true 可以查找到提前暴露的这个对象,一旦创建完成调用 addSingleton(String beanName, Object singletonObject) 将其注册到 singletonObjects 中,这段代码的逻辑见 getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法。

三、bean 的生周期

DefaultSingletonBeanRegistry 不仅管理了 bean 的注册,还管理 bean 的生命周期,包括 bean 的创建和销毁。

3.1 bean 的创建

Spring 中单例只会被创建一次,后续再获取 bean 直接从单例缓存中获取。

  1. 尝试从缓存中查找。getSingleton(beanName) 直接从缓存中获取 bean,也可以指定是否查找提前暴露的 bean(也就是正在创建的 bean)。allowEarlyReference=true 时会查找正在创建的 bean。
  2. 直接创建 bean。当从缓存中获取不到时,直接会调用 getSingleton(beanName, singletonFactory) 方法创建单例 bean。因为创建的时候会存在依赖注入的情况,为了解决可能存在的循环依赖问题,Spring 创建 bean 的原则是不等 bean 创建完成就会将创建 bean 的 ObjectFactory 提早曝光加入到缓存中,这样通过 getSingleton(beanName, true) 就可以在缓存中直接查找到这个 bean 的 ObjectFactory。

3.1.1 从缓存中获取

public Object getSingleton(String beanName) {
// 参数 true 设置标识允许时期依赖
return getSingleton(beanName, true);
} protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1. 在已经创建完成的 singletonObjects 集合中查找
Object singletonObject = this.singletonObjects.get(beanName);
// 2. 如果这个 bean 正在创建,则继续尝试从 earlySingletonObjects 中查找
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 3. 当某些方法需要提前初始化的时候则会调用 addSingletonFactory 方法
// 将对应的 ObjectFactory 初始化策略存储在 singletonFactories
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 调用预先设定的 getObject 方法
singletonObject = singletonFactory.getObject();
// 记录在缓存中,earlySingletonObjects 与 singletonFactories 互斥
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

这个方法步骤如下:

  1. 首先尝试从 singletonObjects 里面获取实例
  2. 如果获取不到再从 earlySingletonObjects 里面获取
  3. 如果还获取不到,再尝试从 singletonFactories 里面获取 beanName 对应的 ObjectFactory,然后调用这个 ObjectFactory 的 getObject 来创建 bean,并放到 earlySingletonObjects 里面去,并且从 earlySingletonObjects 里面 remove 掉这个 ObjectFactory

而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是在 allowEarlyReference=true 的情况下才会使用。

3.1.2 直接创建 bean

上面讲解了从缓存中获取单例的过程,那么,如果缓存中不存在已经加载的单例 bean 就需要从头开始 bean 的加载过程了,而 Spring 中使用 getSingleton 的重载方法 getSingleton(beanName, singletonFactory) 实现 bean 的加载过程。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
// 1. 首先检查对应的 bean 是否已经加载过
// 因为 singleton 模式其实就是复用已创建的 bean,所以这一步是必须的
Object singletonObject = this.singletonObjects.get(beanName);
// 2. 进行 singleton 的 bean 的初始化
if (singletonObject == null) {
// 2.1 容器正在销毁抛出异常
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName);
}
// 2.2 将这个 bean 添加到 singletonsCurrentlyInCreation 集合中,这样就可以判断 bean 是否存在创建
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
// 2.3 初始化 bean,委托给 ObjectFactory 完成
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException ex) {
// 2.4 ?????????
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
} catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 2.5 从 singletonsCurrentlyInCreation 移除该 bean
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 2.6 创建成功,加入缓存
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}

上述代码中其实是使用了回调方法,使得程序可以在单例创建的前后做一些准备及处理操作,而真正的获取单例 bean 的方法其实并不是在此方法中实现的,其实现逻辑是在 ObjectFactory 类型的实例 singletonFactory 中实现的。而这些准备及处理操作包括如下内容:

(1) 检查缓存是否已经加载过

(2) 若没有加载,则记录 beanName 的正在加载状态。

(3) 加载单例前记录加载状态。可能你会觉得 beforeSingletonCreation 方法是个空实现,里面没有任何逻辑,但其实不是,这个函数中做了一个很重要的操作:记录加载状态,也就是通过 this.singletonsCurrentlyInCreation.add(beanName) 将当前正要创建的 bean 记录在缓存中,这样便可以对循环依赖进行检测。

protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) &&
!this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}

(4) 通过调用参数传入的 ObjectFactory 的个体 Object 方法实例化 bean

(5) 加载单例后的处理方法调用。同步骤 (3) 的记录加载状态相似,当 bean加载结東后需要移除缓存中对该 bean 的正在加载状态的记录。

protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) &&
!this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}

(6) 将结果记录至缓存并删除加载 bean 过程中所记录的各种辅助状态。

3.1.3 ObjectFactory 参数

在创建 bean 的过程中,很多工作都交给 ObjectFactory 这个工厂类完成,那它到底是什么呢?

public interface ObjectFactory<T> {
T getObject() throws BeansException;
}

在方法 getSingleton(beanName, singletonFactory)addSingletonFactory(beanName, singletonFactory) 两种都用到了 ObjectFactory,这两处的 ObjectFactory 功能并不是一样的。 前者的 ObjectFactory 是用于创建 bean,属于创建型 ObjectFactory,而后者只是简单的持有 bean,属于引用型 ObjectFactory,保存在 singletonFactories 集合中用于解决循环依赖的问题。

(1) 创建型 ObjectFactory

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
}

(2) 引用型 ObjectFactory

在 createBean 创建 bean 的过程中,在实例化 bean 后就会将这个 bean 提前暴露出来,这样就可以提前在缓存中拿到正在创建的 bean。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) {
// 1. 反射创建 bean
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance(); // 2. 将这个 bean 通过 addSingletonFactory 暴露到缓存中,这样指定 allowEarlyReference=true 就可以提前查找到
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// getEarlyBeanReference 默认直接将这个 bean 返回了
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
} // 3. 之后再进行属性注入和初始化等操作
Object exposedObject = bean;
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}

3.1.4 bean 的状态管理

bean 进行循环依赖检查与两个集合有关:

  • inCreationCheckExclusions 如果 bean 创建完成则添加到该集合中,这样如果包含要检查的 bean 就不用再检查 singletonsCurrentlyInCreation 了。
  • singletonsCurrentlyInCreation bean 创建开始时先添加到这个集合中,创建成功后删除
// 如果 inCreation=false 则说明对象已经创建成功,直接添加到 inCreationCheckExclusions 集合中,否则就删除
// 这样在进行循环依赖检查时,当这个集合包含该 bean 时就不用检查 singletonsCurrentlyInCreation
public void setCurrentlyInCreation(String beanName, boolean inCreation) {
Assert.notNull(beanName, "Bean name must not be null");
if (!inCreation) {
this.inCreationCheckExclusions.add(beanName);
} else {
this.inCreationCheckExclusions.remove(beanName);
}
} // isCurrentlyInCreation 和 isSingletonCurrentlyInCreation 区别还是没看明白???
public boolean isCurrentlyInCreation(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName));
}
// isActuallyInCreation 方法只有在 isCurrentlyInCreation 中调用,不明白为什么还要单独抽出来
protected boolean isActuallyInCreation(String beanName) {
return isSingletonCurrentlyInCreation(beanName);
}
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}

3.2 bean 的依赖管理

bean 创建成功后需要注册 bean 之前的依赖关系,这样销毁时才能将依赖它的 bean 也同时销毁

3.2.1 依赖管理

(1) 注册依赖

// 保存当前 bean 内的所有 bean。containingBeanName -> containedBeanName
public void registerContainedBean(String containedBeanName, String containingBeanName) {
synchronized (this.containedBeanMap) {
Set<String> containedBeans =
this.containedBeanMap.computeIfAbsent(containingBeanName, k -> new LinkedHashSet<>(8));
if (!containedBeans.add(containedBeanName)) {
return;
}
}
registerDependentBean(containedBeanName, containingBeanName);
} // dependentBeans 保存依赖我的所有 bean。containedBeanName -> containingBeanName
// dependenciesForBeanMap 保存我依赖的所有 bean。containingBeanName -> containedBeanName
public void registerDependentBean(String beanName, String dependentBeanName) {
// 查找 bean 的注册名称
String canonicalName = canonicalName(beanName); synchronized (this.dependentBeanMap) {
// jdk8 如果 key 不存在设置 value,否则返回 oldValue
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
// 如果已经注册直接返回
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}

当然如果这个 bean 有销毁方法,也会注册其 DisposableBean

public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean);
}
}

(2) 依赖查找

  • isDependent 查找两个 bean 的依赖关系
  • getDependentBeans 查找依赖这个 bean 的所有 bean
  • getDependenciesForBean 查找这个 bean 依赖的所有 bean

isDependent 查找两个 bean 的依赖关系。如果 dependentBeanName 依赖 beanName 则返回 true,这其中会存在间接依赖的情况,如 beanA -> beanB -> beanC,查询 beanA -> beanC 的关系。

protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
} private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
// 1. alreadySeen 是已经查找过的 bean,这里面的 bean 都不存在依赖关系,如果存在则已经返回 true 了
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
// 2. 获取 bean 的注册名称
String canonicalName = canonicalName(beanName);
// 3. 查找依赖 beanName 的所有 bean,如果有则肯定有依赖,否则还要查找间接依赖
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
// 4. 逐个查找间接依赖
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}

3.3 bean 的销毁

// 销毁所有 bean
public void destroySingletons() {
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
} String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
} this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear(); clearSingletonCache();
} // 销毁指定的 bean
public void destroySingleton(String beanName) {
removeSingleton(beanName);
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}

真正的销毁在 destroyBean 中完成。

protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// 1. 首先将依赖这个 beanName 的全部销毁
Set<String> dependencies;
// ConcurrentHashMap 为什么还需要同步???
synchronized (this.dependentBeanMap) {
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName);
}
} // 2. 真正销毁该 beanName
if (bean != null) {
bean.destroy();
} // 3. 销毁 containedBeans
Set<String> containedBeans;
synchronized (this.containedBeanMap) {
containedBeans = this.containedBeanMap.remove(beanName);
}
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
destroySingleton(containedBeanName);
}
} // 4. 清理 dependentBeanMap 中残存的 beanName 记录
synchronized (this.dependentBeanMap) {
for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, Set<String>> entry = it.next();
Set<String> dependenciesToClean = entry.getValue();
dependenciesToClean.remove(beanName);
if (dependenciesToClean.isEmpty()) {
it.remove();
}
}
} // 5. 清理 dependenciesForBeanMap
this.dependenciesForBeanMap.remove(beanName);
}

每天用心记录一点点。内容也许不重要,但习惯很重要!

Spring IOC(三)单例 bean 的注册管理的更多相关文章

  1. Spring单例Bean和线程安全

    Spring的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?例如对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Sevlet线程来处理请求,引入Spring框 ...

  2. Spring IoC BeanDefinition 的加载和注册

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...

  3. Spring IOC 容器源码分析 - 创建单例 bean 的过程

    1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...

  4. Spring IOC 容器源码分析 - 获取单例 bean

    1. 简介 为了写 Spring IOC 容器源码分析系列的文章,我特地写了一篇 Spring IOC 容器的导读文章.在导读一文中,我介绍了 Spring 的一些特性以及阅读 Spring 源码的一 ...

  5. Spring(六)核心容器 - 注册单例 Bean 实例、SingletonBeanRegistry 简介

    前言 上篇文章我们对注册 Bean 的核心类 BeanDefinitionRegistry 进行了讨论,这里的注册 Bean 是指保存 Bean 的相关信息,也就是将 Bean 定义成 BeanDef ...

  6. 【Spring源码分析】非懒加载的单例Bean初始化过程(下篇)

    doCreateBean方法 上文[Spring源码分析]非懒加载的单例Bean初始化过程(上篇),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下 ...

  7. 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作

    前言 之前两篇文章[Spring源码分析]非懒加载的单例Bean初始化过程(上篇)和[Spring源码分析]非懒加载的单例Bean初始化过程(下篇)比较详细地分析了非懒加载的单例Bean的初始化过程, ...

  8. Spring源码分析:非懒加载的单例Bean初始化前后的一些操作

    之前两篇文章Spring源码分析:非懒加载的单例Bean初始化过程(上)和Spring源码分析:非懒加载的单例Bean初始化过程(下)比较详细地分析了非懒加载的单例Bean的初始化过程,整个流程始于A ...

  9. Spring源码分析:非懒加载的单例Bean初始化过程(下)

    上文Spring源码分析:非懒加载的单例Bean初始化过程(上),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下AbstractAutowireC ...

随机推荐

  1. js-for (var in )遍历顺序乱了

    存放的key 为如下: “01”,“02”,“03”,········“10”,“11”,“12” 遍历之后“10”,“11”,“12”, “01”,“02”,“03”,········ 解决办法:把 ...

  2. SSM框架下,使用ajax请求上传文件(doc\docx\excel\图片等)

    1.准备工作 1.1.添加上传必要jar包 <dependency> <groupId>commons-io</groupId> <artifactId> ...

  3. 解题7(FindFirstOnlyOne)

    题目描述 找出字符串中第一个只出现一次的字符 输入描述: 输入一个非空字符串 输出描述: 输出第一个只出现一次的字符,如果不存在输出-1 示例1 输入 asdfasdfo 输出 o 代码如下: pac ...

  4. openjdk1.8 源码地址

    http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/656ab3b39178/src/

  5. Java Timer

    Java Timer 定时类,主要用来执行定时任务 Timer管理所有要执行的定时任务 TimerTask封装好的定时任务 常见的用法 MyTask myTask = new MyTask(); Ti ...

  6. JMeter调试工具--Debug Sampler(转载)

    转载自 http://www.cnblogs.com/fengpingfan Debug Sampler添加路径:[添加 / Sampler / Debug Sampler],面板设置如下: 打开JM ...

  7. 二叉树的镜像(python)

    题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ ...

  8. git config --global user.email

    加上这个就ok

  9. c# 文件过大时清空原有内容重新写入

    FileStream fs = new FileStream("E:\\Test\\HistoryData.txt", FileMode.Append, FileAccess.Wr ...

  10. js阻止时间冒泡事件——event.stopPropagation()

    1. 作用:不再派发事件. 2. 语法: html代码: <div class="oreder-cont" ng-click="Orderdetails()&quo ...