JDK:1.8
IDE:Idea 2019
SpringBoot:2.1.5
把整个过程总结在前面:
搭建源码阅读环境
这里你也可以不用搭建,直接使用Idea的源码下载功能也可以,但这样拿到的源码是只读的,如果你想在阅读过的地方加上注释则很困难。另外我们搭建的是Springboot的源码阅读环境,并不是Spring-framework的,前者是基于maven构建的项目,后者是基于gradle,两者搭建方法不一样。
1.到github上下载源码:https://github.com/spring-projects/spring-boot。选择release:
找到2.1.5版本,当然你也可以选择其他版本,这个随意。拉到版本页面的最底部,现在源码:
2.下载下来后,解压到某个位置,然后用idea打开主目录下的pom文件,选择open as project。首次打开项目可能会比较久,要解析许多依赖。
很多教程里面还会教你如何安装maven和grdle,2019版本的idea并不需要额外安装这两个东西,它已经自带了。
3.项目打开之后,看到的目录是这样的:
设置项目的jdk版本为java8,选择maven选项卡,点击那个m图标:
输入mvn clean install -DskipTests -Pfast
这步操作也需要挺长的时间,等maven执行完毕,这个项目已经配置了一个启动配置,直接点击debug就能运行起来:
4.写一个新的maven项目作为测试项目。选择选择最上层的目录,右键,基于maven新添加一个module:spring-boot-study。如图:
5.在pom文件里面加上依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
2.1.5.RELAESE是通过我们下载的源码生成的,如果你选择其他的版本,maven会从远程仓库里面下载,那么你调试的代码也就是不是你下载的代码了。
你选择的时候,idea提示器会提示你哪个版本本地就有,比如2.1.5这个版本和其他的版本标志是不一样的。看上图。
6.在项目的App类里面添加如下代码:
@SpringBootApplication
public class App {
public static void main(String[] args)
{
SpringApplication.run(App.class,args);
}
}
这里有个坑,原来我们创建的module,其目录结构是继承自主项目的,这会导致这个项目运行的时候报一个错误:
这个问题的解决办法也比较简单,只需要把原来的目录结构删了,重新创建一下App这个类,其目录结构如下:
然后鼠标放到main方法内部,右键,Debug ‘App’,程序就能正常debug了,结果如图:
到现在为止,SpringBoot的源码阅读环境就搭建好了。现在可以在这个study模块上写一些测试代码,跟踪代码,分析源码了。
值得一提的是,SpringBoot这个项目大量依赖Spring Framework,因此,如果单纯下载下来SpringBoot的源码,很多代码仍然无法跟踪进去,这点后面我们在分析ioc源码的时候你就会发现。
分析SpringBoot的IOC过程:
1.run方法返回值类型是ConfigurableApplicationContext,这里的继承关系是:
ConfigurableApplicationContext=》ApplicationContext=》ListableBeanFactory=》BeanFactory
上面列举的全是接口,BeanFactory是最顶层的接口,spring里面各式各样的context,比如AnnotationConfigApplicationContext、XmlServletWebServerApplicationContext等都继承自它。那么这个ConfigurableApplicationContext具体是由哪个类实现的呢,持续跟踪代码会跟踪到下面的方法:
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
这个方法实际上告诉了我们,在2.1.5版本中,总共有三种context的实现,具体使用哪一种,取决于webApplicationType,而webApplicationType则是通过扫描包里面的依赖,根据依赖内容而得出的(是否包含web相关的依赖等)。具体怎么得到的,由于这块和ioc关系不大,这里不追究了。
2持续跟踪run方法,一直跟踪到
refreshContext(context);
这个方法,在这个方法之前的工作都是spring相关的准备工作,和ioc关系不大,这个方法是用来实现ioc相关功能的核心方法,整个ioc的生命周期,都在这个方法里。
3.持续跟踪代码,最后跟踪到AbstractApplicationContext这个抽象类的refresh方法,这个类直接继承自ConfigurableApplicationContext接口,该类属于spring framework,不属于springboot,因此如果你尝试修改它,会发现它是只读的,是因为我们并没有把spring framework的代码下载下来。方法的具体实现如下,这个ioc的生命周期发生的操作,都在这里了。具体每步的功能是做什么,官方都添加了英文注释,但是这个注释有些简单,我又额外添加了一些中文注释进来:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//非常重要的一步,进行包扫描,把bean定义扫描出来,
//什么是bean定义,在spring里面表现为BeanDefination,
//它用来描述bean,比如是否是单例,是否是懒加载等等信息,
//这些信息都是从xml配置信息或者注解信息里面读出来。
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//非常重要的一步,完成bean的实例化
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
4.第一步扫描包,它的代码实现在下面这个方法里面:
invokeBeanFactoryPostProcessors(beanFactory);
扫描包的目的是把所有的bean定义扫描出来,然后放到下面这个map里面:
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
由此可见,bean定义的缓存类型是ConcurrentHashMap类型,值的类型是BeanDefinition,它是一个接口,具体的实现有很多类,spring会根据不同的bean定义方案实现不同的类。它总共有哪些实现,看下图:
在执行这步代码之前,2.1.5版本的springboot里面它的值是6,具体内容如下:
其中就包含了我们的入口类,app。
在这个方法执行完之后,会把我们定义的bean也放进来以及系统定义的bean加载进来,看下执行后它的值:
我标注的bean是我自己定义的一个测试类,其他基本都是系统自己的bean。
5.这些bean定义缓存决定了ioc容器处理bean的方案,那么是不是意味着它只能通过配置或者注解来决定呢,答案是否定的,其实在这个过程中我们是可以干预的,干预是使用beanfactory后置处理器(注意不是bean的后置处理器)来处理的,参考下面的代码:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
GenericBeanDefinition genericBeanDefinition=(GenericBeanDefinition)beanFactory.getBeanDefinition("singletonTest");
genericBeanDefinition.setLazyInit(true);
}
}
这样就可以把我们定义的bean设置为懒加载了。当然了,你也可以通过在bean定义的时候加上注解实现这个功能,这俩效果是一样的:
@Component
@Lazy
public class SingletonTest {
public SingletonTest()
{
System.out.println("SingletonTest被实例化");
}
public void test()
{
}
}
5.包扫描结束后,后来又到了一步非常关键的方法:finishBeanFactoryInitialization(beanFactory)。这个方法的作用是完成非懒加载的类的单例类的实例化。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
//关键步骤,上面的基本都是准备工作。
beanFactory.preInstantiateSingletons();
}
6.重点关注下preInstantiateSingletons这个方法,其代码如下:
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
//实例化所有的单例的、非懒加载的、非抽象的bean。
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
//后置处理所有的后置处理方法
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
在第一次轮询中,做了一个判断,判断是否是factorybean,什么是factorybean,参考我另一篇博文https://blog.csdn.net/dap769815768/article/details/100862413。如果不是直接通过getBean方法就可以了。
7.getBean最终会走到doGetBean方法:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
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 = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
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);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
//重要,真实地创建bean实例的方法。
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
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());
}
}
return (T) bean;
}
这里需要关注的是getSingleton这个方法,它是bean的实际实例化方法,包含了属性注入的部分。
8.getSingleton方法:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
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 + "'");
}
//解决循环依赖问题,使用一个set保存正在实例化的bean。
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//调用传进来的回调createBean,创建bean。
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;
}
}
首先是通过调用下面的方法,把正在实例化的bean缓存起来:
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
然后调用
singletonObject = singletonFactory.getObject();
执行回调createBean(beanName, mbd, args),进入到真正的bean创建方法中。
9.createBean方法:
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;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
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,完整的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);
}
}
在doCreateBean方法,整个bean就被创建了,该方法源码如下:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//通过某个策略创建一个bean的包装实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//通过类的包装实例获取到类的实例,但未完成属性注入。
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//完成属性注入
populateBean(beanName, mbd, instanceWrapper);
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) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
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 " +
"'getBeanNamesOfType' 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;
}
8.循环依赖。spring中如果循环依赖的方式是构造器注入,那么会抛出异常:The dependencies of some of the beans in the application context form a cycle。如果是属性注入,要求两边不能全部是多例,否则也会抛出上面的异常。如果A是多例,B是单例,那么不可以对A进行自动注入,否则仍然会抛出上面的异常。原因很简单:
实例化A=》注入A的依赖B=》实例化B=》注入B的依赖A=》由于A是多例,所以不会获取之前实例化一半的A,而是重新实例化一个A=》程序回到最初的一步,进入死循环。
而如果反过来,则没问题:
实例化B=》注入B的依赖A=》实例化A=》注入A的依赖B=》B是单例,所以直接将之前实例化一半的B的引用传给A=》自动注入完成。
这里面其实就是谁先实例化的问题。多例的那个不能先实例化,必须后实例化,才不会导致报循环依赖的异常。