相关阅读
简介
本文主要简单分析DefaultListableBeanFactory
的getBean
实现。
Demo
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.getBean("demo");
}
getBean
方法由AbstractBeanFactory
实现,且有多个重载实现,代码如下:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
/**
* @param name 待查找的Bean的名称
* @param requiredType 用于转换查找到的Bean为指定类型
* @param args 创建Bean实例时使用的参数,若查找的Bean不存在则需要创建
*/
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
throws BeansException {
return doGetBean(name, requiredType, args, false);
}
简析
getBean
内部直接调用doGetBean
实现,doGetBean
实现较为复杂,主要逻辑如下:
- 根据name得到最终的BeanName,因为
- 传入的name可能带有
&
前缀(表示FactoryBean
),需要除去&
前缀; - 传入的name可能是BeanName的别名(的别名…),需要找到BeanName;
- 传入的name可能带有
- 尝试从缓存中获取已注册的单例Bean(这是解决单例循环依赖的关键);
- 如果缓存中存在单例Bean,且传入的
args
为空,那么直接从单例Bean中获取最终对象;- 因为得到的Bean可能是
BeanFactory
,而最终想要获取的却是BeanFactory.getObject()
返回的对象;
- 因为得到的Bean可能是
- 否则需要创建Bean;
- 如果是多例的循环依赖情况,则直接抛出异常;
- 如果存在父
BeanFactory
,且本BeanFactory
中不存在该Bean的BeanDefinition
,则尝试从父BeanFactory
获取Bean; - 校验Bean的
BeanDefinition
; - 检查dependsOn属性,确保Bean创建前该属性已被创建;
- 根据不同的Scope创建Bean,分为:单例、原型、其它Scope类型三种情况;
- 单例情况;
- 原型情况;
- 其它Scope情况;
- 适配Bean,如果指定了
requiredType
,且获取到的Bean不是requiredType
类型,则需要转换Bean为指定requiredType
类型;
1. 获取最终的BeanName
- 传入的name可能带有
&
前缀(表示FactoryBean
),需要除去&
前缀; - 传入的name可能是BeanName的别名(的别名…),需要找到BeanName;
代码如下:
// AbstractBeanFactory
String beanName = transformedBeanName(name);
protected String transformedBeanName(String name) {
// 先是去除FactoryBean的前缀如果有的话
// 再找到对应的BeanName如果是别名的话
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
// BeanFactoryUtils.java
String FACTORY_BEAN_PREFIX = "&";
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
// 没有前缀标识,直接返回
return name;
}
// 此处做了缓存处理,如果name已经存在(被处理过)则直接返回缓存的值,否则循环去除前缀标识,再结果缓存
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
// 去除前缀标识
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
// 如果还存在前缀标识,则继续处理
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
// SimpleAliasRegistry.java
public String canonicalName(String name) {
// 假设当前name为最终的BeanName
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
// 尝试获取以canonicalName为别名的BeanName
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
// 存在,则更新最终的BeanName
canonicalName = resolvedName;
}
}
// 直到以canonicalName为别名的BeanName不存在,说明canonicalName就是最终的BeanName
while (resolvedName != null);
return canonicalName;
}
2. 尝试从缓存中获取已注册的单例Bean
这是解决单例循环依赖的关键,获取到的单例Bean可能正处于创建中,代码如下:
// 先尝试从缓存中获取已经注册的单例Bean
Object sharedInstance = getSingleton(beanName);
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName) {
// true表示支持获取早期引用,即还未完全创建的Bean
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 尝试从一级缓存(缓存完全创建的单例Bean)中获取beanName对应的单例Bean
Object singletonObject = this.singletonObjects.get(beanName);
// 如果对应的单例Bean不在一级缓存中,且处于正在创建过程中,则
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 尝试从二级缓存(缓存还未完全创建的单例Bean,即BeanFactory.getObject()的返回值)中获取beanName对应的单例Bean
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果对应的单例Bean不在二级缓存中,且支持获取早期引用
if (singletonObject == null && allowEarlyReference) {
// 加锁,防止并发
synchronized (this.singletonObjects) {
// 再次从一级缓存中获取beanName对应的单例Bean
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 依旧不存在,则再尝试从二级缓存中获取beanName对应的单例Bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
// 依旧不存在,则尝试从三级缓存(缓存创建单例Bean的ObjectFactory)中获取beanName对应的单例Bean
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 三级缓存中存在,则使用ObjectFactory.getObject()获取单例Bean
singletonObject = singletonFactory.getObject();
// 将ObjectFactory创建的单例Bean放入二级缓存
// ObjectFactory创建的单例Bean虽然创建成功,但是还未完全创建(还未属性填充、Bean后置处理等)
this.earlySingletonObjects.put(beanName, singletonObject);
// 移除三级缓存的对应缓存,已经使用过,无需缓存了
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
3. 从已注册的单例Bean中获取最终对象
如果缓存中存在已注册单例Bean(可能还未完全创建),且传入的args
为空(这个条件值得深入思索),那么直接从单例Bean中获取最终对象;
为什么不直接返回呢?因为缓存的Bean可能是FactoryBean
,而最终获取的Bean是FactoryBean.getObject()
的返回;
代码如下:
if (sharedInstance != null && args == null) {
// 缓存中存在,且未指定实例化参数
if (logger.isTraceEnabled()) {
// 当前Bean实例是否正在创建中
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 从缓存中的Bean实例获取最终的Bean
// 如果当前Bean实例是FactoryBean,那么需要通过其getObject获取最终的Bean如果需要的话
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
// AbstractAutowireCapableBeanFactory.java
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
String currentlyCreatedBean = this.currentlyCreatedBean.get();
if (currentlyCreatedBean != null) {
registerDependentBean(beanName, currentlyCreatedBean);
}
// 调用父类AbstractBeanFactory的实现
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
// AbstractBeanFactory.java
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果查找的Bean是FactoryBean类型
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
// 缓存的单例Bean却不是FactoryBean类型,则抛出异常
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
// 设置BeanDefinition的isFactoryBean属性
mbd.isFactoryBean = true;
}
return beanInstance;
}
// 查找的Bean不是FactoryBean类型
// 缓存的单例Bean可能是FactoryBean类型,也可能不是
if (!(beanInstance instanceof FactoryBean)) {
// 如果缓存的单例Bean不是FactoryBean,那么可以直接返回
return beanInstance;
}
// 缓存的单例Bean是FactoryBean类型
Object object = null;
if (mbd != null) {
// 设置BeanDefinition的isFactoryBean属性
mbd.isFactoryBean = true;
}
else {
// 尝试从缓存中获取FactoryBean创建的Bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 缓存中还不存在,则需要从FactoryBean中创建
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {
// 获取FactoryBean的BeanDefinition
mbd = getMergedLocalBeanDefinition(beanName);
}
// FactoryBean的BeanDefinition是否是程序本身定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 获取FactoryBean创建的Bean,且缓存创建的Bean如果可以的话
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
// FactoryBeanRegistrySupport.java
protected Object getCachedObjectForFactoryBean(String beanName) {
// 从缓存中获取FactoryBean创建的Bean
return this.factoryBeanObjectCache.get(beanName);
}
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 如果FactoryBean是单例,且已经完全创建
// 通过单例FactoryBean创建Bean,此时应该都完全创建,除非A线程在创建FactoryBean时,B线程恰好调用getBean获取其维护的Bean的行为
// 同一线程会再次进入该方法,但此时FactoryBean会完全创建,如通过还未创建的FactoryBean获取其维护的Bean时,会先通过getSingleton(String beanName, ObjectFactory<?> singletonFactory)创建出FactoryBean,然后再进入本方法根据完全创建的FactoryBean获取其维护的Bean;
if (factory.isSingleton() && containsSingleton(beanName)) {
// 加锁,防止并发
synchronized (getSingletonMutex()) {
// 先尝试从缓存中获取FactoryBean创建的Bean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 缓存中不存在FactoryBean创建的Bean,则需要FactoryBean创建Bean
object = doGetObjectFromFactoryBean(factory, beanName);
// 再次尝试从缓存中获取FactoryBean创建的Bean,防止FactoryBean.getObject()的用户实现递归执行该方法时,重复对创建的Bean进行后置处理
// 比如FactoryBean.getObject()再次调用getBean访问自身,就会递归进入该方法,而在终止递归那一层调用中,会将完全创建的Bean加入factoryBeanObjectCache缓存中,那么其他层在这里就需要判断是否已经存在完全创建好的Bean
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
// 如果缓存中存在,则表示已经经过后置处理,那么直接使用
// 读者可以思考这种情况是如何产生的
// 后续【场景分析】会提到这种情况
object = alreadyThere;
}
else {
// 否则需要经过后置处理如果需要的话,并且缓存
// 是否需要后置处理
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// 如果beanName对应的单例正在创建中,则直接返回(感觉不会存在这种情况,因为进入该分支时已满足containsSingleton(beanName))
return object;
}
// 单例创建前处理,即缓存到表示正在创建中单例的Map,标记正在创建状态
beforeSingletonCreation(beanName);
try {
// Bean后置处理,Bean前置处理是在创建Bean的时候
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
// 单例创建后处理,即从表示正在创建中单例的Map移除缓存,清除正在创建状态
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
// 如果Bean完全创建,则可以缓存
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
// FactoryBean不是单例,或者FactoryBean还未完全创建
// 如果FactoryBean不是单例,那么每次都需要重新创建Bean,且创建的Bean无需缓存,相关状态也无需标记
// 如果FactoryBean还未完全创建,那么(大部分)会直接返回null,抛出BeanCurrentlyInCreationException异常;如果FactoryBean在创建过程中存在通过getBean获取维护的Bean的行为,递归进入该方法,那么就会出现这种异常情况
else {
// FactoryBean创建Bean
Object object = doGetObjectFromFactoryBean(factory, beanName);
// 是否需要后置处理
if (shouldPostProcess) {
try {
// Bean后置处理
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 调用FactoryBean的getObject()方法创建Bean
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// 不接受FactoryBean.getObject()返回null值
// 如果FactoryBean创建的Bean为null,那么FactoryBean可能还未完成初始化:大部分的FactoryBean完成初始化前getObject()会直接返回null
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
// 如果FactoryBean还在创建过程中,则抛出异常
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
// FactoryBean.getObject()确实返回null,那么就包装为NullBean
object = new NullBean();
}
return object;
}
// DefaultSingletonBeanRegistry.java
public boolean containsSingleton(String beanName) {
// 从一级缓存中获取缓存的单例Bean
return this.singletonObjects.containsKey(beanName);
}
protected void beforeSingletonCreation(String beanName) {
// 如果该BeanName需要创建检查,则缓存到正在创建单例集合中
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
// 缓存失败,该BeanName已经被缓存,则说明已经正在创建中
throw new BeanCurrentlyInCreationException(beanName);
}
}
protected void afterSingletonCreation(String beanName) {
// 如果该BeanName需要创建检查,则从正在创建单例集合中移除
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
// 移除失败,说明该BeanName并没有正在创建中
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
4. 创建Bean
到这里,说明缓存中不存在单例Bean,或者传入的args有效,那么需要考虑创建Bean,代码如下:
else {
if (isPrototypeCurrentlyInCreation(beanName)) {
// 如果是多例的循环依赖情况,则直接抛出异常
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
// 如果存在父`BeanFactory`,且本`BeanFactory`中不存在该Bean的`BeanDefinition`,则尝试从父`BeanFactory`获取Bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
// 如果不是仅类型检查,则标记当前Bean为已创建状态,即将该BeanName对应的BeanDefinition缓存
markBeanAsCreated(beanName);
}
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
if (requiredType != null) {
beanCreation.tag("beanType", requiredType::toString);
}
// 获取并校验Bean的`BeanDefinition`
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 检查dependsOn属性
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 + "'");
}
// 注册dependsOn属性
registerDependentBean(dep, beanName);
try {
// 获取dependsOn属性,确保该属性在本Bean创建前已被创建
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 开始创建Bean
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
protected void markBeanAsCreated(String beanName) {
// 还未创建该beanName
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// 既然需要创建Bean,那么
// 设置beanName对应的BeanDefinition的stale属性为true,表示需要重新生成
clearMergedBeanDefinition(beanName);
// 缓存该beanName被创建状态
this.alreadyCreated.add(beanName);
}
}
}
}
protected void cleanupAfterBeanCreationFailure(String beanName) {
synchronized (this.mergedBeanDefinitions) {
// 移除该beanName被创建状态
this.alreadyCreated.remove(beanName);
}
}
创建Bean时,还需要区分Scope类型,分为以下三种情况:
- 单例;
- 原型;
- 其它情况,则根据具体的Scope类型创建;
1. 原型
if (mbd.isSingleton()) {
// 获取单例
// 先从缓存中获取,若缓存中不存在,则通过传入的ObjectFactory的getObject()方法获取
// 传入的ObjectFactory的getObject()方法就是直接调用createBean方法创建Bean
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建Bean
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// 销毁单例Bean
destroySingleton(beanName);
throw ex;
}
});
// 如果beanInstance是FactoryBean,那么需要通过其getObject获取最终的Bean如果需要的话
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 加锁,防止并发
synchronized (this.singletonObjects) {
// 再次判断单例是否已经被创建
// 这一步可以避免当指定args参数且单例Bean已经创建时,重复创建Bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
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 + "'");
}
// 单例创建前处理,即缓存到表示正在创建中单例的Map,标记为正在创建状态
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 通过ObjectFactory.getObject()创建Bean,即调用createBean
singletonObject = singletonFactory.getObject();
// 设置新单例创建成功标识
newSingleton = true;
}
catch (IllegalStateException ex) {
// 再次判断该BeanName是否存在,如果存在则不抛出异常
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;
}
// 单例创建后处理,即从表示正在创建中单例的Map移除缓存,清除正在创建状态
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 如果新单例创建成功,则缓存到单例集合中
addSingleton(beanName, singletonObject);
}
}
return 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);
}
}
public void destroySingleton(String beanName) {
// 从缓存中移除
removeSingleton(beanName);
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
// 销毁Bean,如果存在的话
destroyBean(beanName, disposableBean);
}
// AbstractAutowireCapableBeanFactory.java
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Bean实例化预处理,BeanPostProcessor的返回值(比如创建了代理)如果有效则直接退出
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
// 由于是直接退出,所以该Bean需要在resolveBeforeInstantiation中进行初始化后处理
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) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// Bean实例化前预处理
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// Bean存在,则进行初始化后处理
// 因为后续会直接返回该Bean,需要在此处进行初始化后处理
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 单例则尝试从缓存中获取
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 调用MergedBeanDefinitionPostProcessor处理
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
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");
}
// 将暴露早起引用的ObjectFactory添加到三级缓存中
// 如果在本Bean创建过程中,存在其它Bean访问(依赖)本Bean(循环依赖),就会通过ObjectFactory获取到本Bean的早期引用,见DefaultSingletonBeanRegistry.getSingleton(String beanName)方法
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
// 填充Bean属性(这是造成循环依赖的入口)
populateBean(beanName, mbd, instanceWrapper);
// 初始化Bean,包含初始化预处理和后处理,这步可能会改变exposedObject(比如存在代理)
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);
}
}
// 检查早期单例引用
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
// 该beanName对应的单例已经被缓存到一级或者二级缓存中,说明被其它Bean依赖,存在循环依赖
// 从三级缓存获取到早期引用后,会将Bean移至二级缓存
if (exposedObject == bean) {
// 单例没有被改变(比如说:代理),则可以直接使用
exposedObject = earlySingletonReference;
}
// 单例被改变(比如说:代理),则校验本Bean早期引用是否已被注入到其它完全创建的Bean中
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
// 存在已经完全创建的Bean注入了当前Bean的早期引用
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
// 因为本Bean在initializeBean时被改变(比如存在代理),早期引用已经无效
// 所以需要抛出异常,不支持这种情况下的循环依赖
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.");
}
}
}
}
// 注册销毁Bean信息
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
// 如果存在InstantiationAwareBeanPostProcessor,则进行处理
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
// 支持InstantiationAwareBeanPostProcessor对早期Bean引用做修改
// Spring AOP就是实现该接口返回代理Bean
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
// 实例化后处理,在属性设置之前
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
// 属性设置
// 此时会注入依赖,可能存在循环依赖,单例是通过三级缓存提前暴露创建中的Bean来规避
...
}
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 初始化预处理
// 注意和applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)的区别
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用初始化方法进行初始化操作
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 初始化后处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
2. 原型
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 标记当前beanName的正在创建状态
beforePrototypeCreation(beanName);
// 创建Bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 清除当前beanName的正在创建状态
afterPrototypeCreation(beanName);
}
// 如果当前prototypeInstance是FactoryBean,那么需要通过其getObject获取最终的Bean如果需要的话
beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 标记当前beanName的正在创建状态
protected void beforePrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal == null) {
// 不存在任何BeanName,那么直接添加当前beanName即可
this.prototypesCurrentlyInCreation.set(beanName);
}
else if (curVal instanceof String) {
// 已存在一个BeanName,则构造集合进行存储
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
}
else {
// 已存在BeanName集合,则将当前beanName加入BeanName集合
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}
// 清除当前beanName的正在创建状态
protected void afterPrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal instanceof String) {
// 单个beanName,即就是beanName,直接移除
this.prototypesCurrentlyInCreation.remove();
}
else if (curVal instanceof Set) {
// 多个则仅移除当前beanName
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.remove(beanName);
if (beanNameSet.isEmpty()) {
// 移除空集合
this.prototypesCurrentlyInCreation.remove();
}
}
}
3. 其它情况,则根据具体的Scope类型创建
else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
}
// 获取Scope类型
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
// 构造ObjectFactory用于创建Bean
Object scopedInstance = scope.get(beanName, () -> {
// 标记当前beanName的正在创建状态
beforePrototypeCreation(beanName);
try {
// 创建Bean
return createBean(beanName, mbd, args);
}
finally {
// 清除当前beanName的正在创建状态
afterPrototypeCreation(beanName);
}
});
// 如果scopedInstance是FactoryBean,那么需要通过其getObject获取最终的Bean如果需要的话
beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new ScopeNotActiveException(beanName, scopeName, ex);
}
}
5. 适配Bean
如果指定了requiredType
,且获取到的Bean不是requiredType
类型,则需要转换Bean为指定requiredType
类型,代码如下:
return adaptBeanInstance(name, beanInstance, requiredType);
<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
// 如果指定了类型,且得到的Bean类型不是指定的类型,那么就需要转换类型
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 如果存在用户指定的类型转换器则使用,否则使用默认的SimpleTypeConverter
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
// 转换失败,抛出异常
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
// 返回成功转换后的Bean
return (T) 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());
}
}
return (T) bean;
}
场景分析
为了加强这一步流程的理解,准备了些测试代码,请读者分析测试代码的创建流程以及结果;
XML配置文件都一致,里面配置了待测试的Bean信息,具体如下:
<bean id="demo" class="DemoFactoryBean"></bean>
1. FactoryBean
构造函数中访问自身
测试代码
public class DemoFactoryBean implements FactoryBean<Demo> {
public static DefaultListableBeanFactory factory;
public DemoFactoryBean() {
factory.getBean("demo");
}
@Override
public Demo getObject() throws Exception {
return new Demo();
}
@Override
public Class<?> getObjectType() {
return Demo.class;
}
public static void main(String[] args) {
DefaultListableBeanFactory factory = new XmlBeanFactory(new FileSystemResource("/path/application-bean.xml"));
DemoFactoryBean.factory = factory;
factory.getBean("demo");
}
}
class Demo {
}
测试结果
报错信息如下:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demo' defined in file [/src/main/resources/application-bean.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [DemoFactoryBean]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'demo': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1232)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [DemoFactoryBean]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'demo': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:224)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1326)
... 8 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'demo': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:227)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at DemoFactoryBean.<init>(DemoFactoryBean.java:15)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:211)
2. FactoryBean.getObject()
中无限制访问自身
测试代码
public class DemoFactoryBean implements FactoryBean<Demo> {
public static DefaultListableBeanFactory factory;
public DemoFactoryBean() {
}
@Override
public Demo getObject() throws Exception {
return (Demo) factory.getBean("demo");
}
@Override
public Class<?> getObjectType() {
return Demo.class;
}
public static void main(String[] args) {
DefaultListableBeanFactory factory = new XmlBeanFactory(new FileSystemResource("/path/application-bean.xml"));
DemoFactoryBean.factory = factory;
factory.getBean("demo");
}
}
class Demo {
}
测试结果
报错信息如下:
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class org.springframework.beans.factory.BeanCreationException
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:176)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1884)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1284)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:345)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
3. FactoryBean.getObject()
中有限制访问自身
测试代码
public class DemoFactoryBean implements FactoryBean<Demo> {
public static DefaultListableBeanFactory factory;
public DemoFactoryBean() {
}
public static int i = 3;
@Override
public Demo getObject() throws Exception {
if (i-- > 0) {
return (Demo) factory.getBean("demo");
} else {
return new Demo();
}
}
@Override
public Class<?> getObjectType() {
return Demo.class;
}
public static void main(String[] args) {
DefaultListableBeanFactory factory = new XmlBeanFactory(new FileSystemResource("/path/application-bean.xml"));
DemoFactoryBean.factory = factory;
factory.getBean("demo");
}
}
class Demo {
}
测试结果
无报错;
4. FactoryBean
的InitializingBean.afterPropertiesSet
实现访问自身,不指定args参数
测试代码
public class DemoFactoryBean implements FactoryBean<Demo>, InitializingBean {
public static DefaultListableBeanFactory factory;
public DemoFactoryBean() {
}
@Override
public void afterPropertiesSet() throws Exception {
factory.getBean("demo");
}
@Override
public Demo getObject() throws Exception {
return new Demo();
}
@Override
public Class<?> getObjectType() {
return Demo.class;
}
public static void main(String[] args) {
DefaultListableBeanFactory factory = new XmlBeanFactory(new FileSystemResource("/path/application-bean.xml"));
DemoFactoryBean.factory = factory;
factory.getBean("demo");
}
}
class Demo {
}
测试结果
无报错;
5. FactoryBean
的InitializingBean.afterPropertiesSet
实现访问自身,指定args参数
测试代码
public class DemoFactoryBean implements FactoryBean<Demo>, InitializingBean {
public static DefaultListableBeanFactory factory;
public DemoFactoryBean() {
}
@Override
public void afterPropertiesSet() throws Exception {
factory.getBean("demo", "args");
}
@Override
public Demo getObject() throws Exception {
return new Demo();
}
@Override
public Class<?> getObjectType() {
return Demo.class;
}
public static void main(String[] args) {
DefaultListableBeanFactory factory = new XmlBeanFactory(new FileSystemResource("/path/application-bean.xml"));
DemoFactoryBean.factory = factory;
factory.getBean("demo");
}
}
class Demo {
}
测试结果
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demo' defined in file [/src/main/resources/application-bean.xml]: Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'demo': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'demo': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:227)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:218)
at DemoFactoryBean.afterPropertiesSet(DemoFactoryBean.java:19)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800)
问题探索
1. 从缓存获取到单例Bean,为何只能当未指定args时才可以使用?
首先要明确的是,当单例Bean缓存存在时,即使指定args了,后续也不会再次创建单例Bean,因为DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory<?> singletonFactory)
方法在创建Bean之前会再次尝试从缓存中获取单例Bean,此时获取到会直接使用;
指定args,那么创建的Bean可能不一致;
递归调用factory.getBean("demo")
会使用到缓存,但递归调用factory.getBean("demo", "args")
却无法用到缓存,且会抛出异常;详见【场景分析】的第4、5中情况;
2. 二级缓存就可以解决单例循环依赖问题,为什么还要引入三级缓存?
既要解决循环依赖,又不想破坏设计好的Bean生命周期管理;
Spring很好地设计了Bean的生命周期管理,但是循环依赖的存在会破坏Bean的生命周期管理;
为了解决单例循环依赖,且不想破坏Bean的生命周期管理,Spring引入了三级缓存(其实是一种惰性思想);
Spring三级缓存存储的是提供Bean早期引用的ObjectFactory
,这是用于解决循环依赖;提供创建的方法而没有直接创建Bean早期引用,这是不想破坏Bean的生命周期管理;
一旦存在循坏依赖,那么三级缓存就会被使用,为了确保单例,需要将创建出来的Bean早期引用放入二级缓存,同时移除三级缓存(防止再次创建出另一个Bean的早期引用),这会破坏Bean的生命周期管理;
如果不存在循环依赖,那么三级缓存就不会被使用,Bean的生命周期管理自然也就不会被破坏;
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/4771.html