在Spring中,Bean对象的定义、注册和获取的过程通常涉及到如下的一些底层类:
Spring中Bean对象的定义、注册和获取过程是Spring IoC(控制反转)容器的核心。以下是这个过程的具体流程:
<bean id="myBean" class="com.example.MyClass">
<property name="property1" value="Value1" />
bean>
SingletonBeanRegistry是Spring框架中的一个接口,主要用于管理单例Bean的注册。它提供了一种机制,可以在运行时将预先实例化的对象(单例对象)注册到Spring容器中, 这些对象可以在之后被应用程序中的其他部分获取和使用。在Spring的IoC(控制反转) 容器中,这个接口主要被用于管理那些不由容器本身创建的对象,例如由用户手动创建的 对象,或者是由其他框架或工厂方法创建的对象。
public interface SingletonBeanRegistry {
// 这个方法用于向注册表中注册一个新的单例Bean。参数beanName是Bean的名称,而singletonObject则是要注册的单例对象。
void registerSingleton(String beanName, Object singletonObject);
//根据单例bean的名称获取这个单例bean
@Nullable
Object getSingleton(String beanName);
//判断是不是包含指定名称的单例bean
boolean containsSingleton(String beanName);
//这个方法返回注册表中所有已经注册的单例Bean的名称。返回的是一个字符串数组
String[] getSingletonNames();
//这个方法返回注册表中单例bean的数量
int getSingletonCount();
//单例模式下带来的最严重的问题就是线程安全问题,
//getSingletonMutex() 方法在 SingletonBeanRegistry 接口中返回一个mutex(互斥锁)对象,该对象用于单例Bean的外部同步。
// 当你需要自定义的同步逻辑或者在进行某些需要线程安全保障的操作时,你可以使用这个返回的mutex对象来进行同步控制。
Object getSingletonMutex();
}
pring 框架中一个非常重要的类,主要用于提供单例 bean 的缓存和注册服务。这个类实现了 SingletonBeanRegistry 接口,并定义了一些管理单例 bean 的核心方法
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//允许保留的警告的最多数量
private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;
//下面的几个map就是用来存储Bean的容器了,singletonObjects这个是一个ConcurrentHashMap,它是线程安全的,初始容量为256,用于存储已经完全初始化并可以被使用的单例对象。键是bean的名称,值是对应的bean实例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//这个Map存储了对象工厂(ObjectFactory),这些工厂负责产生单例对象。当一个单例bean被创建但未初始化时,它将会被存储在这个Map中
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
//这个Map存储了早期的单例对象,即已经实例化但还未完全初始化(例如,还没有进行属性注入)的bean。这些早期的bean主要用于解决循环依赖的问题(两个或者更多的bean彼此依赖,形成了一个依赖的循环)
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
//这是一个Set,存储了所有已经注册的单例bean的名字,按照注册的顺序排列
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
//这是一个Set,存储了当前正在创建的bean的名字,这主要用于检测bean的循环依赖
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//这是一个Set,存储了在创建检查中被排除的bean的名字。这些bean不会被用于循环依赖检查
private final Set<String> inCreationCheckExclusions =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//这是一个Exception的Set,用于收集在创建单例过程中被忽略的异常
@Nullable
private Set<Exception> suppressedExceptions;
//这是一个布尔值,用于标识当前是否正在销毁单例beans
private boolean singletonsCurrentlyInDestruction = false;
//这是一个Map,用于存储所有的DisposableBean实例。DisposableBean是Spring中的一个接口,实现这个接口的bean在容器销毁时会调用其destroy方法,进行清理工作
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
//这是一个Map,存储了包含关系的beans。键是包含其他beans的bean的名称,值是被包含的beans的名称的Set
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
//这是一个Map,存储了依赖关系的beans。键是依赖其他beans的bean的名称,值是被依赖的beans的名称的Set
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
//这是一个Map,存储了依赖关系的beans。键是被依赖的bean的名称,值是依赖这个bean的beans的名称的Set
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
//这个方法用于向注册表中注册一个新的单例 bean。参数 beanName 是 bean 的名称
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
//判断参数是否为空
Assert.notNull(beanName, "Bean name must not be null");
Assert.notNull(singletonObject, "Singleton object must not be null");
//因为是单例,所以操作其时不能有别的线程,所以这里需要加锁
synchronized (this.singletonObjects) {
//这句代码和下面的判断主要是为了判断当前bean的名称是否已经存在了,如果已经存在了就会抛出IllegalStateException异常
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
//调用addSingleton方法,添加新的bean实例
addSingleton(beanName, singletonObject);
}
}
//该方法用于添加新的单例bean
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//向singletonObjects这个map中添加新的单例的键值对
this.singletonObjects.put(beanName, singletonObject);
//singletonFactories保存一个单例bean被创建但未初始,加入到singletonObjects意味着这个单例bean被创建了,所以需要从工厂中移除
this.singletonFactories.remove(beanName);
//和上面同样的道理
this.earlySingletonObjects.remove(beanName);
//registeredSingletons存储已经被实例化的单例bean的名称,这里将新创建的单例bean的名称保存到set集合中
this.registeredSingletons.add(beanName);
}
}
//这个方法的作用是添加一个单例工厂
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
//
synchronized (this.singletonObjects) {
//它首先检查singletonObjects这个map中是否已经包含了给定名称的bean。如果已经包含了,那么这个方法就什么都不做,直接返回。
if (!this.singletonObjects.containsKey(beanName)) {
//把给定的singletonFactory添加到singletonFactories这个map中。在这个map中,键是bean的名称,值是对应的ObjectFactory
this.singletonFactories.put(beanName, singletonFactory);
//从earlySingletonObjects这个map中移除给定名称的bean。earlySingletonObjects这个map存储了早期的单例对象,即已经实例化但还未完全初始化的bean。这些早期的bean主要用于解决循环依赖的问题
this.earlySingletonObjects.remove(beanName);
//把给定的bean的名称添加到registeredSingletons这个set中。registeredSingletons这个set存储了所有已经注册的单例bean的名称
this.registeredSingletons.add(beanName);
}
}
}
//重写SingletonBeanRegistry的getSingleton方法,获得指定名称的单例bean
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
//主要目的是获取指定名称的单例对象。如果需要,它还会创建这个单例对象的早期引用,这段代码的作用是获取给定bean名称的单例实例。
// 它首先尝试从singletonObjects映射中获取完全初始化的单例实例。如果无法获取,则检查该bean是否正在创建中,如果是,则尝
// 试从earlySingletonObjects映射中获取已实例化但未完全初始化的单例实例。如果仍然无法获取,则根据allowEarlyReference
// 参数的值,决定是否创建早期引用(解决循环依赖问题)。如果允许创建早期引用,则尝试从singletonFactories映射中获取bean工
// 厂,并使用该工厂创建早期引用。最后,将创建的单例实例存储在singletonObjects或earlySingletonObjects映射中,以便后续使用。
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//尝试从singletonObjects映射(已经完全初始化的单例对象映射)中获取bean实例
Object singletonObject = this.singletonObjects.get(beanName);
//如果在singletonObjects中找不到对应的实例,且该bean当前正在创建中(通过isSingletonCurrentlyInCreation(beanName)检查),则进入下一步
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//尝试从earlySingletonObjects映射(已实例化但未完全初始化的对象映射)中获取bean实例
singletonObject = this.earlySingletonObjects.get(beanName);
//如果在earlySingletonObjects中也找不到,且参数allowEarlyReference为true,表示允许创建早期引用(主要是解决循环依赖问题),则进入下一步
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// 在singletonObjects上同步,确保线程安全,然后再次尝试从singletonObjects和earlySingletonObjects映射中获取bean实例
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//如果以上尝试都未能获取到bean实例,那么尝试从singletonFactories映射(存储bean工厂的映射)中获取对应的bean工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//如果获取到了bean工厂,就用它来创建bean实例(早期引用),然后将这个早期引用存储在earlySingletonObjects映射中,并从singletonFactories映射中移除对应的bean工厂
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
//这个方法可以接受一个名为 singletonFactory 的 ObjectFactory 参数,它的功能主要是获取指定名称的单例对象,如果没有找到,它将使用提供的 ObjectFactory 来创建一个。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
//在已经初始化的单例中查找指定名称的bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//如果当前正在销毁单例,这段代码是Spring框架的一个安全机制,用于防止在容器正在销毁单例bean时创建新的单例bean
//是 Spring Framework 中用于获取单例对象的核心方法之一。它首先在已经初始化的单例对象中查找指定名称的 bean,
// 如果找到了就直接返回。如果没有找到,则会尝试从指定的工厂中获取实例。在获取实例之前,它会进行循环依赖检查,
// 并记录是否在单例创建的过程中出现过异常。如果成功获取到了实例,则会将其添加到单例对象池中,并返回该实例。
// 如果在获取实例的过程中出现了异常,则会将异常记录下来,并抛出 BeanCreationException 异常。
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//循环依赖检查
beforeSingletonCreation(beanName);
boolean newSingleton = false;
//recordSuppressedExceptions,记录是否在单例创建的过程中出现过异常
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
//如果没有出现过异常,则创建一个新的LinkedHashSet来记录异常
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//尝试从指定的工厂中获取实例
singletonObject = singletonFactory.getObject();
//标记是不是新的实例
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
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;
}
//添加到销毁的集合
afterSingletonCreation(beanName);
}
//如果是新的单例对象就添加到
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
//向异常集合中添加新的异常
protected void onSuppressedException(Exception ex) {
synchronized (this.singletonObjects) {
if (this.suppressedExceptions != null && this.suppressedExceptions.size() < SUPPRESSED_EXCEPTIONS_LIMIT) {
this.suppressedExceptions.add(ex);
}
}
}
//按照单例的名称删除已经被初始化的单例对象
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
//判断是否有存在指定名称的bean
@Override
public boolean containsSingleton(String beanName) {
return this.singletonObjects.containsKey(beanName);
}
//获得所有已经初始化的实例的民初
@Override
public String[] getSingletonNames() {
synchronized (this.singletonObjects) {
return StringUtils.toStringArray(this.registeredSingletons);
}
}
//获得已经初始化的bean的数量
@Override
public int getSingletonCount() {
synchronized (this.singletonObjects) {
return this.registeredSingletons.size();
}
}
//用来设置一个bean是否正在被创建
public void setCurrentlyInCreation(String beanName, boolean inCreation) {
Assert.notNull(beanName, "Bean name must not be null");
//如果正在创建就加入到inCreationCheckExclusions集合中
if (!inCreation) {
this.inCreationCheckExclusions.add(beanName);
}
//如果没有在创建,就从这个集合中删除这个bean(可能这个集合中不存在这个bean的名称)
else {
this.inCreationCheckExclusions.remove(beanName);
}
}
//判断这个bean是否正在被创建
public boolean isCurrentlyInCreation(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName));
}
protected boolean isActuallyInCreation(String beanName) {
return isSingletonCurrentlyInCreation(beanName);
}
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
//这段代码的作用是在创建单例bean之前进行检查,以确保没有循环依赖的问题。
// 如果当前正在创建的单例bean已经在创建过程中,则会抛出一个BeanCurrentlyInCreationException异常。
// 如果beanName不在inCreationCheckExclusions列表中,则会将其添加到singletonsCurrentlyInCreation集合中,
// 以便检查循环依赖。
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
//这段代码是 Spring Framework 中用于在单例对象创建完成之后进行的一些清理工作的方法之一。它会检查当前单例对象是否处于创建状态,如果是,
// 则将其从单例对象的创建集合中移除。如果单例对象不处于创建状态,则会抛出 IllegalStateException 异常,提示该单例对象并不处于创建状态。
//在 Spring Framework 中,为了避免循环依赖的问题,它会在创建单例对象之前先将该对象的名称添加到单例对象的创建集合中。在单例对象创建完成之后,
// 就需要将其从创建集合中移除,以便下一次获取该单例对象时不会再次触发循环依赖检查
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
//销毁bean的集合
public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean);
}
}
//这段代码是 Spring Framework 中用于注册一个 Bean 包含的其他 Bean 的方法之一。它会将被包含的 Bean 的名称和包含它的 Bean 的名称作为参数传入,
// 然后将被包含的 Bean 的名称添加到包含它的 Bean 的 containedBeanMap 属性中。如果 containedBeanMap 中已经存在该被包含的 Bean,则直接返回,
// 否则将其添加到 containedBeanMap 中。接着,该方法会调用 registerDependentBean 方法,将被包含的 Bean 和包含它的 Bean 之间建立依赖关系,
// 以确保在包含它的 Bean 销毁时,被包含的 Bean 也会被销毁。
public void registerContainedBean(String containedBeanName, String containingBeanName) {
synchronized (this.containedBeanMap) {
//如果指定的containingBeanName在containedBeanMap中不存砸,就创建一个新的LinkedHashSet,
//computeIfAbsent 是 Java 8 中 Map 接口新增的方法,它的作用是:如果指定 key 对应的 value 不存在,就使用 mappingFunction 计算出新的 value,
// 并将其存储到 Map 中。如果指定 key 对应的 value 已经存在,则直接返回该 value,不会再次执行 mappingFunction。
Set<String> containedBeans =
this.containedBeanMap.computeIfAbsent(containingBeanName, k -> new LinkedHashSet<>(8));
if (!containedBeans.add(containedBeanName)) {
return;
}
}
registerDependentBean(containedBeanName, containingBeanName);
}
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
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是否有依赖关系
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) {
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
String canonicalName = canonicalName(beanName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
protected boolean hasDependentBean(String beanName) {
return this.dependentBeanMap.containsKey(beanName);
}
public String[] getDependentBeans(String beanName) {
Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
if (dependentBeans == null) {
return new String[0];
}
synchronized (this.dependentBeanMap) {
return StringUtils.toStringArray(dependentBeans);
}
}
public String[] getDependenciesForBean(String beanName) {
Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(beanName);
if (dependenciesForBean == null) {
return new String[0];
}
synchronized (this.dependenciesForBeanMap) {
return StringUtils.toStringArray(dependenciesForBean);
}
}
//销毁单例bean
public void destroySingletons() {
if (logger.isTraceEnabled()) {
logger.trace("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
//用来标记当前正在执行销毁过程,不能再创建新的bean
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
//获得当前正在销毁集合中的bean的名称
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();
}
protected void clearSingletonCache() {
synchronized (this.singletonObjects) {
//删除所有的bean存储信息
this.singletonObjects.clear();
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
this.singletonsCurrentlyInDestruction = false;
}
}
//销毁指定的名称的bean
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}
//删除该单例的依赖信息
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// Trigger destruction of dependent beans first...
Set<String> dependencies;
synchronized (this.dependentBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
if (logger.isTraceEnabled()) {
logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
}
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName);
}
}
// Actually destroy the bean now...
if (bean != null) {
try {
bean.destroy();
}
catch (Throwable ex) {
if (logger.isWarnEnabled()) {
logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
}
}
}
// Trigger destruction of contained beans...
Set<String> containedBeans;
synchronized (this.containedBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
containedBeans = this.containedBeanMap.remove(beanName);
}
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
destroySingleton(containedBeanName);
}
}
// Remove destroyed bean from other beans' dependencies.
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();
}
}
}
// Remove destroyed bean's prepared dependency information.
this.dependenciesForBeanMap.remove(beanName);
}
/**
* Exposes the singleton mutex to subclasses and external collaborators.
* Subclasses should synchronize on the given Object if they perform
* any sort of extended singleton creation phase. In particular, subclasses
* should not have their own mutexes involved in singleton creation,
* to avoid the potential for deadlocks in lazy-init situations.
*/
@Override
public final Object getSingletonMutex() {
return this.singletonObjects;
}
}
“早期引用”(early reference)是指一个已经被实例化但尚未完全初始化的Bean对象。在Spring的Bean生命周期中,Bean的创建大致经历以下步骤:
- 实例化:这个阶段是指 Spring 容器根据 Bean 的定义创建出一个 Bean 的实例,这个实例还没有被初始化,也没有被注入任何属性值;
- 属性填充:在这个阶段,Spring 容器将会把配置文件中的属性值或者注解中的属性值注入到 Bean 实例中;
- 初始化:在这个阶段,Spring 容器会调用 Bean 实例中的初始化方法,以完成 Bean 的初始化工作。这个阶段可以通过实现 InitializingBean 接口或者在配置文件中指定 init-method 方法来实现。
在这个过程中,如果在实例化之后、初始化之前,Bean被其他Bean引用,那么这就是一个早期引用。早期引用主要用于解决循环依赖的问题。假设我们有两个单例Bean,A和B,其中A依赖B,B依赖A。当Spring试图创建A时,发现A依赖B,于是Spring转而去创建B;然后在创建B时,又发现B依赖A,此时如果没有早期引用,那么就会陷入无限循环中,无法完成Bean的创建。为了解决这个问题,Spring引入了早期引用的概念。在上述例子中,当Spring创建A时,发现A依赖B,于是Spring转而去创建B;在创建B时,发现B依赖A,此时Spring并不会再次尝试创建A,而是直接返回A的早期引用。由于早期引用是在填充属性之前创建的,因此它可以打破循环依赖,使得Bean的创建能够继续进行
在 Spring 中,单例 Bean 的销毁流程可以分为以下几个步骤:
- 调用 DisposableBean 接口的 destroy() 方法:如果一个 Bean 实现了 DisposableBean 接口,那么在容器关闭时,Spring 会自动调用该 Bean 的 destroy() 方法进行销毁操作。
- 调用 @PreDestroy 注解标注的方法:如果一个 Bean 使用了 @PreDestroy 注解标注了一个方法,那么在容器关闭时,Spring 会自动调用该方法进行销毁操作。
- 手动调用 destroy-method 指定的方法:如果在配置文件中指定了 destroy-method 属性,那么在容器关闭时,Spring 会自动调用指定的方法进行销毁操作。
- 调用自定义销毁方法:如果一个 Bean 定义了自己的销毁方法,那么在容器关闭时,Spring 会自动调用该方法进行销毁操作。这种情况下,需要在配置文件中明确指定该方法的名称。
在容器关闭时,Spring 会按照上述顺序依次执行销毁操作,确保单例 Bean 能够被正确销毁。需要注意的是,Spring 并不会销毁原型(prototype)作用域的 Bean,因为它们的生命周期不受 Spring 容器的管理。
AbstractBeanFactory 是 Spring Framework 中 BeanFactory 接口的抽象实现类,它是 Spring IoC 容器的核心组件之一,负责管理 Bean 的创建、配置、依赖注入和生命周期等方面的逻辑。具体来说,AbstractBeanFactory 主要有以下作用:
- 提供 Bean 的注册和获取功能:AbstractBeanFactory 提供了 registerBeanDefinition() 方法用于向 IoC 容器中注册 Bean 定义,以及 getBean() 方法用于从容器中获取 Bean 实例。
- 提供 Bean 的创建和初始化功能:AbstractBeanFactory 负责创建 Bean 实例,并在创建完成后执行一系列的初始化操作,包括依赖注入、Aware 接口回调、初始化方法调用等。
- 提供 Bean 的依赖注入功能:AbstractBeanFactory 负责处理 Bean 之间的依赖关系,将依赖的 Bean 注入到目标 Bean 中。
- 提供 Bean 的生命周期管理功能:AbstractBeanFactory 负责管理 Bean 的生命周期,包括 Bean 的创建、初始化、销毁等过程。在 Bean 创建和销毁的过程中,AbstractBeanFactory 会触发对应的事件,以便其他组件能够对 Bean 的生命周期进行监听和处理。
- 提供容器中 Bean 的查找和管理功能:AbstractBeanFactory 提供了一系列方法,用于查询和管理容器中的 Bean,包括根据名称、类型、注解等方式查找 Bean,以及获取所有 Bean 的名称、类型等信息。
总之,AbstractBeanFactory 是 Spring IoC 容器的核心组件之一,它提供了一系列功能,用于管理 Bean 的创建、配置、依赖注入和生命周期等方面的逻辑。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
//获得指定类型的bean
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
//获得指定名称的bean,并提供构造参数(没有创建时可以创建)
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
throws BeansException {
return doGetBean(name, requiredType, args, false);
}
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//在 Spring 中,Bean 名称可以包含特殊字符,比如点号(.)和斜杠(/),这些特殊字符在 Bean 的定义中具有特殊的含义。
// 为了避免这些特殊字符带来的问题,Spring 使用了一个默认的分隔符(默认为点号),将 Bean 名称中的特殊字符替换成默认分隔符。
String beanName = transformedBeanName(name);
Object bean;
//调用DefaultSingletonBeanRegistry的getSingleton方法,如果是单例就直接获取
Object sharedInstance = getSingleton(beanName);
//AbstractBeanFactory
if (sharedInstance != null && args == null) {
//判断是否开启类Trace级别的日志记录
if (logger.isTraceEnabled()) {
//判断该单例对象是否正在创建
if (isSingletonCurrentlyInCreation(beanName)) {
//记录日志(提示该bean是一个早期引用还没被初始化)
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
//提示该bean是一个缓冲实例(已经被初始化类)
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//getObjectForBeanInstance 方法是 AbstractAutowireCapableBeanFactory 类的一个私有方法,
// 用于从 Bean 实例中获取对应的 Bean 对象。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//如果没有找到指定的单例bean对象,此时就需要创建这个bean了
else {
//它首先检查指定名称的Bean单例实例是否正在创建中,如果是,则抛出BeanCurrentlyInCreationException异常。
// 这是为了避免在Bean实例创建期间发生循环依赖或重复创建的情况
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//创建创建Bean的父工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果父工厂不为空,且工厂中有该Bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//转换Bean的名称
String nameToLookup = originalBeanName(name);
//如果父工厂的类型是AbstractBeanFactory或是其子类
if (parentBeanFactory instanceof AbstractBeanFactory) {
//调用doGetBean方法
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
//如果带有参数,就调用带参数的getBean方法
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// 没有参数就会调用默认的getBean的方法
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
//如果父类工厂不是AbstractBeanFactory或其子类,就会调用这个工厂的getBean方法
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
//标记该bean为已创建,将其添加到已创建bean的集合中,这样可以防止重复创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
//创建一个 StartupStep 实例,这是Spring的新特性,用于监控应用的启动过程,可以帮助我们更好地理解和优化应用的启动过程
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
//通过 getMergedLocalBeanDefinition(beanName) 获取Bean的合并后的定义信息,即 RootBeanDefinition
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查获取的 RootBeanDefinition。如果bean定义的信息有问题,比如说定义的类不能被实例化,那么这个方法会抛出异常
checkMergedBeanDefinition(mbd, beanName, args);
//获取该beam所依赖的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
//存在循环依赖的问题,抛出异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//将这些依赖关系注册到依赖管理的数据结构中(通过 registerDependentBean(dep, beanName))
registerDependentBean(dep, beanName);
try {
//获取Bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//判断是不是单例bean
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//创建bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
//将新创建的单例对象赋值给bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//如果是原型作用域
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
//beforePrototypeCreation(beanName) 和 afterPrototypeCreation(beanName) 是在Bean创建前后的扩展点,
// 用于执行一些自定义的逻辑。
beforePrototypeCreation(beanName);
//创建原型bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
//将创建的原型bean赋值给bean
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//处理自定义作用域
else {
//获得作用域
String scopeName = mbd.getScope();
//判断Scope是否为空
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
//获得作用域的名称
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
//这个get方法是scope.java中的一个方法,这里用lamda表达式实现了生成该bean的工厂
Object scopedInstance = scope.get(beanName, () -> {
//Bean创建前的扩展电
beforePrototypeCreation(beanName);
try {
//创建Bean
return createBean(beanName, mbd, args);
}
finally {
//Bean创建后的扩展点
afterPrototypeCreation(beanName);
}
});
//将生成的Bean赋值给bean
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
//标记创建bean完成
beanCreation.end();
}
}
//这段代码处理的是返回Bean的类型转换。当用户在获取Bean时指定了目标类型,Spring会确保返回的Bean是指定类型或者可以转换为指定类型的实例
if (requiredType != null && !requiredType.isInstance(bean)) {
//检查Bean是否是指定的类型以及用户是有指定了类型
try {
//如果不是指定的类型,则尝试进行类型转换。这是通过 getTypeConverter().convertIfNecessary(bean, requiredType) 方法完成的,
// 其中 getTypeConverter() 返回Bean工厂使用的类型转换器,convertIfNecessary 尝试将Bean转换为目标类型。
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
//如果类型转换成功,返回转换后的Bean。如果转换失败或者转换后的Bean为null,抛出 BeanNotOfRequiredTypeException 异常。
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
//返回bean
return (T) bean;
}
//创建Bean的方法是一个抽象方法交给子类实现
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException;
//解析和返回给定的 RootBeanDefinition 的Bean类。在Spring中,Bean类是Bean的实例化和装配的基础,因此需要对其进行解析。
//将在Spring配置中指定的Bean的类名解析为Java Class对象的过程
@Nullable
protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
//通过调用 mbd.hasBeanClass() 来检查 RootBeanDefinition 是否已经有了关联的Bean类
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
//如果还没有关联的Bean类,那么就需要解析Bean类。这里有两种情况需要考虑:如果系统中已经启用了安全管理器,那么就需要使用 AccessController.doPrivileged
// 来解析Bean类,确保在解析过程中能够正确地管理权限;如果没有启用安全管理器,那么就直接解析Bean类,这是通过 doResolveBeanClass(mbd, typesToMatch) 实现的
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>)
() -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
return doResolveBeanClass(mbd, typesToMatch);
}
}
catch (PrivilegedActionException pae) {
ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
catch (LinkageError err) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
}
//解析bean类的函数主体
@Nullable
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
throws ClassNotFoundException {
//它获取 Bean 的 ClassLoader,这是用于加载 Bean 类的类加载器。同时,也可能
ClassLoader beanClassLoader = getBeanClassLoader();
ClassLoader dynamicLoader = beanClassLoader;
boolean freshResolve = false;
if (!ObjectUtils.isEmpty(typesToMatch)) {
//获取一个临时的类加载器(如果存在的话),在特定的情况下(如织入场景)可能会用到
ClassLoader tempClassLoader = getTempClassLoader();
if (tempClassLoader != null) {
dynamicLoader = tempClassLoader;
freshResolve = true;
if (tempClassLoader instanceof DecoratingClassLoader) {
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
for (Class<?> typeToMatch : typesToMatch) {
dcl.excludeClass(typeToMatch.getName());
}
}
}
}
//获得bean的类名
String className = mbd.getBeanClassName();
//如果bean的类名不为空
if (className != null) {
//对bean的类名其进行评估。评估可能涉及到动态解析表达式。如果类名不等于评估的结果(说明类名被动态解析了),并且解析结果是 Class 类型或 String 类型,
// 那么将返回解析结果的 Class 对象或重新解析类名字符串为 Class 对象。对于其他类型的评估结果,会抛出异常
Object evaluated = evaluateBeanDefinitionString(className, mbd);
if (!className.equals(evaluated)) {
// A dynamically resolved expression, supported as of 4.2...
if (evaluated instanceof Class) {
return (Class<?>) evaluated;
}
else if (evaluated instanceof String) {
className = (String) evaluated;
freshResolve = true;
}
else {
throw new IllegalStateException("Invalid class name expression result: " + evaluated);
}
}
//如果类名被动态解析了(即,解析结果是 String 类型的类名,而不是原来的类名),代码会尝试用当前的类加载器(可能是临时的类加载器)加载类。如果加载失败,会再尝试用 ClassUtils.forName 方法加载类
if (freshResolve) {
// When resolving against a temporary class loader, exit early in order
// to avoid storing the resolved Class in the bean definition.
if (dynamicLoader != null) {
try {
return dynamicLoader.loadClass(className);
}
catch (ClassNotFoundException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
}
}
}
return ClassUtils.forName(className, dynamicLoader);
}
}
// Resolve regularly, caching the result in the BeanDefinition...
//如果类名没有被动态解析(即,类名等于评估的结果),代码会正常解析类,并将解析结果(即 Class 对象)缓存到 Bean 定义中
return mbd.resolveBeanClass(beanClassLoader);
}
}
doGetBean方法是Spring中AbstractBeanFactory的一个核心方法,主要用于获取和创建bean实例。这个方法的主要工作流程如下:
- 首先,检查已存在的单例bean,如果已存在,则直接返回。
- 如果不存在,检查当前是否在创建这个bean,如果是,则返回早期的单例对象。这是为了解决循环依赖问题。
- 如果没有正在创建的单例对象,那么就开始创建新的单例对象。首先,获取bean的定义信息(BeanDefinition),然后根据这个信息创建新的bean实例。
- 在创建新的bean实例时,首先解析bean的类,然后实例化这个类,然后设置bean的属性,最后调用bean的初始化方法。
- 创建新的bean实例后,将它添加到单例缓存中,然后返回。
doGetBean方法实现了bean的完整的创建过程,包括类解析、实例化、属性设置、初始化等步骤。并且,它也处理了单例模式和原型模式,以及循环依赖问题。
Spring框架在解析Bean类的过程中涉及到以下几个主要步骤:
- 资源定位:这是Bean定义的开始阶段,主要是通过Resource接口和ResourceLoader接口实现的。这个阶段会定位到具体的配置文件(例如XML文件,注解配置,Java配置等)。
- 加载Bean定义:这个阶段主要是通过BeanDefinitionReader接口实现的。这个接口会把资源文件中的Bean定义转换成Spring内部的BeanDefinition对象。这个对象包含了Bean的各种元信息,例如Bean的名称、类名、作用域、构造器参数、属性值等。
- 注册Bean定义:这个阶段主要是通过BeanDefinitionRegistry接口实现的。这个接口会把BeanDefinition对象注册到Spring的Bean工厂中。在注册过程中,Spring会检查Bean定义的有效性,并处理别名。
- 解析Bean类:这个阶段主要是通过AbstractBeanDefinition.resolveBeanClass()方法实现的。这个方法会尝试解析Bean类,并检查Bean类是否存在和可访问。
- 创建Bean实例:这个阶段主要是通过AbstractAutowireCapableBeanFactory.createBean()方法实现的。这个方法会根据Bean定义创建Bean的实例,然后进行属性注入和初始化。
- 初始化Bean:这个阶段主要是通过AbstractAutowireCapableBeanFactory.initializeBean()方法实现的。这个方法会调用Bean的初始化方法,并进行Bean的后处理。
- 使用Bean:这个阶段主要是通过BeanFactory.getBean()方法实现的。这个方法会返回Bean的实例,供应用代码使用。
AbstractAutowireCapableBeanFactory是Spring框架中负责创建、初始化、装配以及管理Bean生命周期的核心类。它实现了AutowireCapableBeanFactory接口,并继承自AbstractBeanFactory。主要功能和特点包括:
- 创建Bean实例:它提供了创建Bean实例的核心逻辑,可以根据Bean的定义信息创建出对应的Bean实例,支持多种方式创建实例,如直接使用Java的反射机制、通过工厂方法、通过工厂Bean等。
- 依赖注入:它负责完成依赖注入的操作,包括setter注入和构造器注入两种方式。
- Bean的初始化:在Bean创建完成并且完成依赖注入后,它负责完成Bean的初始化,如调用初始化方法、执行BeanPostProcessors等。
- Bean的销毁:它还负责Bean的销毁过程,如调用销毁方法、执行DisposableBean接口等。
- 处理Bean的作用域:处理Prototype、Singleton、Request、Session、Global等多种作用域的Bean。
- Bean的自动装配:可以根据Bean的类型或名称进行自动装配。
- 类型转换:在执行依赖注入时,能进行必要的类型转换操作。
- 处理循环依赖:在执行依赖注入时,能处理循环依赖的问
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
@Override
@SuppressWarnings("unchecked")
public <T> T createBean(Class<T> beanClass) throws BeansException {
//这行代码创建了一个新的 RootBeanDefinition 对象,该对象描述了Bean的定义。这是通过传入的类(beanClass)作为参数创建的
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
//这行代码将Bean定义的作用域设置为原型
bd.setScope(SCOPE_PROTOTYPE);
//这行代码检查给定的类是否安全地缓存在共享的可扩展类加载器上。如果是,则允许缓存该Bean的元数据
bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
return (T) createBean(beanClass.getName(), bd, null);
}
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//是否开启了Trace级别的日志
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
//创建RooteBenaDefinition对象mbdToduse
RootBeanDefinition mbdToUse = mbd;
//用来解析类名(这是父类AbstractBeanFactory中实现的方法)它尝试解析给定的类名并返回 Class 对象
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
//如果 mbd(Bean 定义)还没有类对象,并且 mbd 的类名不为 null,则创建一个新的 RootBeanDefinition 对象,并设置其类
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
//准备方法覆盖
//这一步调用 mbdToUse 的 prepareMethodOverrides 方法,用于验证和准备覆盖的方法。如果验证失败,则抛出一个异常
try {
//prepareMethodOverrides 是 RootBeanDefinition 的一个方法,主要用于处理和验证 Bean 定义中的方法覆盖(method overrides)设置。
// 这个设置主要用于在 Spring IoC 容器中覆盖或者替换 Spring 管理的 Bean 中的某个方法的行为,这样在后续创建 Bean 实例时,就可以根据这些设置来确定方法的行为。
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
//在实例化 Bean 之前,给 BeanPostProcessors 一个机会返回一个代理实例而不是目标 Bean 实例。如果这个步骤返回的 Bean 不为 null,那么就直接返回这个 Bean。如果在这个步骤出现异常,则抛出一个异常
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//这里开始创建真正的bean实例
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//在Spring框架中,BeanWrapper接口是用于处理Bean属性的主要接口。BeanWrapper的作用是设置和获取属性值(单个或批量),获取属性描述符,以及查询设置属性值的能力。
//BeanWrapper扩展了 PropertyAccessor,这是所有Spring的属性访问器实现的基本接口,包括 BeanWrapper。 BeanWrapper 也提供了分析和管理的方法,以处理嵌套的路径和类型转换。
//当创建一个新的Bean实例并对其进行填充(例如,从XML配置文件中读取的属性值)时,Spring使用 BeanWrapper。同样,当Spring需要读取或修改现有Bean实例的属性时,也会使用 BeanWrapper。
BeanWrapper instanceWrapper = null;
//判断RootbeanDefinition对象的类型
if (mbd.isSingleton()) {
//factoryBeanInstanceCache这个集合中,一个bean的名称对应一个BeanWrapper,如果是当例模式我们就删除这对映射关系
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//表示不是单例模式
if (instanceWrapper == null) {
// 使用 createBeanInstance 方法实例化 Bean。这个过程可能会调用构造函数或工厂方法,或者在特殊情况下,例如对于 FactoryBean 或者通过 CGLIB 创建的 Bean,可能会使用特定的实例化策略
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//由BeanWrapper获得Bean对象
Object bean = instanceWrapper.getWrappedInstance();
//获得该bean的类型(即对应的class对象)
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
//用于在应用程序上下文中创建bean时执行后处理程序。具体来说,它确保应用所有合并的bean定义的后处理程序,并且只在第一次创建bean时执行。如果在后处理程序期间发生异常,则会抛出BeanCreationException
synchronized (mbd.postProcessingLock) {
//这段代码的作用是确保在创建应用程序上下文中的bean时,应用所有合并的bean定义的后处理程序,并且只在第一次创建bean时执行。如果在后处理程序期间发生异常,则会抛出BeanCreationException
if (!mbd.postProcessed) {
try {
//调用applyMergedBeanDefinitionPostProcessors方法,该方法用于应用所有已注册的MergedBeanDefinitionPostProcessor对象,
// 以修改BeanDefinition对象的属性值
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
//将BeanDefinition对象的postProcessed属性设置为true,表示已经完成了所有的后处理操作。
mbd.postProcessed = true;
}
}
//检查BeanDefinition对象的isSingleton方法是否返回true,检查是否允许循环引用,以及检查当前单例对象是否正在创建中
// 用于检查是否允许在创建Bean对象时提前曝光一个单例对象
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//将当前对象添加到一个单例工厂
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//初始化bean实例
Object exposedObject = bean;
try {
//调用 populateBean 方法,该方法用于填充 Bean 的属性值。
populateBean(beanName, mbd, instanceWrapper);
//调用 initializeBean 方法,该方法用于初始化 Bean,并返回一个可公开的 Bean 对象
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
//检查是够需要提前暴露单例bean,以避免循环引用问题
if (earlySingletonExposure) {
//根据bean的名称获得这个单例bean
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {//如果 Bean 实例是集合 BeanWrapper 获得的,则将其替换为提前暴露的单例 Bean 实例(类型检查)
exposedObject = earlySingletonReference;
}
//这段代码的作用是在检查循环依赖时,如果某个 Bean 的依赖中存在“原始”版本的 Bean,则抛出异常。具体来说,它会检查当前 Bean 是否存在依赖关系,
// 如果存在,则遍历依赖关系中的每个 Bean,如果该 Bean 不是仅用于类型检查,则将其添加到 actualDependentBeans 集合中。如果 actualDependentBeans
// 不为空,则抛出 BeanCurrentlyInCreationException 异常,该异常表示当前 Bean 正在创建过程中,但其依赖的其他 Bean 已经使用了它的“原始”版本,
// 而不是最终版本。这通常是类型匹配过于“热切”的结果,可以通过关闭 allowEagerInit 标志来解决。
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
//遍历每一依赖的bean
for (String dependentBean : dependentBeans) {
//如果一个单例 Bean 只是为了类型检查而被创建,就从单例缓存中移除该 Bean。
//在 Spring 容器中,当一个 Bean 的依赖被注入时,Spring 会检查这些依赖的类型是否匹配。如果依赖的类型不匹配,Spring 会抛出异常。
// 为了避免这种情况,Spring 会在创建 Bean 实例之前,先创建一个“原型” Bean 实例,用来检查依赖的类型是否正确。如果类型匹配,再创
// 建真正的 Bean 实例。这个“原型” Bean 实例就是为了类型检查而被创建的。
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
// actualDependentBeans.add(dependentBean) 的作用是将dependentBean添加到
// `actualDependentBeans` 集合中。在这段代码中,它的作用是将当前 Bean 的依赖中不是仅用于
// 类型检查的 Bean 添加到 `actualDependentBeans` 集合中,以便后续判断是否存在循环依赖。
actualDependentBeans.add(dependentBean);
}
}
//"类型匹配过于热切" 是指在 Spring 容器中,当容器在创建 Bean 的时候,会尝试去匹配该 Bean 所依赖的其他 Bean 的类型。
// 如果匹配成功,就会将这些依赖注入到该 Bean 中。但是有时候,容器会过于热切地去匹配这些依赖,导致匹配出来的 Bean 并不
// 是最终的 Bean 实例,而是用于类型检查的“原型” Bean 实例。这样就可能会导致循环依赖等问题。因此,建议在使用类型匹配时,
// 要谨慎使用,避免出现这种情况。
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] 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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
@Override
public int getBeanDefinitionCount() {
return this.beanDefinitionMap.size();
}
}
BeanPostProcessor 是 Spring 框架中一个非常重要的功能接口,它允许我们在 Spring IoC 容器实例化 Bean 之后,执行额外的处理操作。BeanPostProcessor 接口定义了两个方法:postProcessBeforeInitialization 和 postProcessAfterInitialization。
- postProcessBeforeInitialization:这个方法在任何 Bean 初始化方法(如 InitializingBean.afterPropertiesSet 或者自定义的 init 方法)调用之前执行。我们可以在这个方法中对 Bean 进行额外的处理。
- postProcessAfterInitialization:这个方法在所有 Bean 初始化方法调用之后执行。我们可以在这个方法中进行后置处理。
BeanPostProcessor 在 Spring 中被广泛应用,许多重要的 Spring 功能,如 AOP、注解处理等,都是通过 BeanPostProcessor 实现的。
doCreateBean 方法是 Spring Framework 中创建 Bean 的底层方法。它是 AbstractAutowireCapableBeanFactory 类中的一个方法,用于创建和初始化一个 Bean 实例。在创建 Bean 实例之前,它会调用 resolveBeforeInstantiation 方法来解析 Bean 实例化之前需要处理的操作。然后,它会使用 createBeanInstance 方法来创建一个新的 Bean 实例,并使用 applyMergedBeanDefinitionPostProcessors 方法来应用 BeanDefinition 合并后的后置处理器。接着,它会使用 populateBean 方法来填充 Bean 的属性值,并使用 initializeBean 方法来初始化 Bean。最后,它会将 Bean 注册到容器中,并返回一个可公开的 Bean 实例。因此,doCreateBean 方法是 Spring Framework 中创建 Bean 的核心方法之一。
DefaultListableBeanFactory的主要功能如下:
- 创建并管理Bean:DefaultListableBeanFactory可以负责创建新的Bean实例,并对其进行初始化和配置。
- Bean的生命周期管理:DefaultListableBeanFactory可以管理Bean的整个生命周期,包括Bean的创建、初始化、属性设置和销毁。
- Bean的依赖注入:DefaultListableBeanFactory支持Bean的依赖注入,即可以自动地将需要的其他Bean注入到一个Bean中。
- Bean的查找和枚举:DefaultListableBeanFactory提供了查找和枚举所有Bean的能力。
Bean定义的注册和解注册:通过实现BeanDefinitionRegistry接口,DefaultListableBeanFactory还可以注册新的Bean定义,并删除已有的Bean定义。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
//将bean的名称以及对应的BeanDefinition关联起来的集合
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
//判断beanDefinition的类型是不是AbstractBeanDefinition
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
/**
* validate方法是AbstractBeanDefinition的一个方法,它用于验证bean定义的内容是否有效。具体来说,它会检查如下几个方面:
* 1. bean的类名是否已经设置,或者至少factory bean的名称和工厂方法已经设置
* 2. 如果bean是单例,那么它不能同时是抽象的和lazy-init的
* 3. bean的方法覆盖是否有效
* 4. 如果bean有父bean,那么父bean必须已经存在
* 5. 其他一些基本的合法性检查
*/
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
//查看当前的bean是否已经存在beanDefinition了
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
//isAllowBeanDefinitionOverriding方法是DefaultListableBeanFactory类的一个方法,它返回一个布尔值,用来判断是否允许覆盖同名的Bean定义。
//如果isAllowBeanDefinitionOverriding返回true,那么可以用新的Bean定义覆盖旧的Bean定义。
//如果返回false,则不允许覆盖。如果尝试覆盖,将抛出BeanDefinitionOverrideException异常。
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
//现在已经存在的beanDefinition的role和新的beanDefinition的定义
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
//将新的beanDefinition加入到beanDefinitionMap中,替换到原来的定义
this.beanDefinitionMap.put(beanName, beanDefinition);
}
//如果当前的集合中不存在指定bean名称的BeanDefinition
else {
//用于检查当前 BeanFactory 是否已经开始创建bean
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) {
//将新的BeanDefinition添加到map中
this.beanDefinitionMap.put(beanName, beanDefinition);
//BeadDefinition的数量+1
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
//将原来的beanDefinition的名称都添加到新的集合
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
//在 Spring 中,通常情况下,Bean 的创建和注册是由 Spring 容器自动完成的。但在某些情况下,你可能需要手动创建和注册 Bean。比如,
// 在编程式地使用 Spring 容器时,或者在需要动态地创建和注册 Bean 时。
//
//当你手动注册了一个单例 Bean 时,Spring 容器会把这个 Bean 的名称添加到一个特定的列表中,这个列表用于存储所有手动注册的单例
// Bean 的名称。removeManualSingletonName 方法就是用于从这个列表中移除指定的 Bean 名称
removeManualSingletonName(beanName);
//这样做的原因主要是考虑到线程安全性和不可变性。在多线程环境下,如果有多个线程同时读写 beanDefinitionNames 列表,那么可能会出现数据不一致的情况。
// 为了避免这种情况,我们在修改列表之前,先创建一个新的列表,然后再进行修改。修改完成之后,再将新的列表赋值给 beanDefinitionNames。这样可以保证
// 在任何时刻,其他线程看到的 beanDefinitionNames 列表都是一个完整且一致的列表,而不会出现中间状态。
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//如果新的beanDefinition是一个单例
if (existingDefinition != null || containsSingleton(beanName)) {
//resetBeanDefinition 方法是 Spring DefaultListableBeanFactory 类中的一个方法,
// 主要功能是清除 Bean 定义缓存,以及所有关联的 Bean 的相关信息
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
在Spring框架中,bean的角色(role)是一个用于指示bean在应用中的角色或责任的概念。具体来说,BeanDefinition接口定义了三种角色:
- ROLE_APPLICATION:这种类型的bean通常是应用中的顶层bean,它们在业务逻辑中扮演核心角色。这些bean通常是我们自己定义和编写的bean。(对应常数值为0)
- ROLE_SUPPORT:这种类型的bean通常用于某些特定的内部角色,并且不是业务逻辑的一部分。例如,可能为了实现某种特定的基础设施功能或者系统级服务而创建的bean。(对应常数值为1)
- ROLE_INFRASTRUCTURE:这种类型的bean完全是Spring内部使用的,它们通常是Spring框架自身的一部分。这些bean对于Spring框架的用户来说是透明的,他们不需要直接使用这些bean。
这个角色的概念主要用于提供一种分类bean的方式,对于大型的Spring应用来说,了解bean的角色可以帮助更好地理解和管理bean。但是,在编写代码的时候,我们通常不需要直接使用这个概念,因为大部分情况下,我们自己编写的bean都是ROLE_APPLICATION类型的。(对应常数值为2)