只有单例模式下的循环依赖才可以,其他模式会报错。
A依赖B、B依赖A 形成一个依赖环。spring
的解决方案是,实例化A,之后将A封装到一个ObjectFactory
对象中存储。对A进行属性填充的时候,发现有B需要实例化,则去实例化B,实例化B的时候也会将B封装到一个ObjectFactory
对象中存储。B实例化完之后,会去填充B的属性,这是发现有A属性需要填充,这是不再会去创建A而是从封装了A对象的ObjectFactory
中直接取。从而完成B的属性填充,继而完成了A的属性填充。
本次源码分析中案例是UrlService
和UrlService2
相互依赖。系统首先实例化UrlService
,再实例化UrlService2
。仔细观察截图可见下面的截图有两次处理依赖处理。我们的本篇的原码也是以下图的方法压栈顺序依次分析。分析者需要有对spring的源码整体有一定的把握,可以参考我的另外两篇文章
。
下面进行代码分析篇。
#AbstractBeanFactory
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
...省略
// 创建bean的入口
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
return (T) bean;
}
# DefaultSingletonBeanRegistry
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
//省略
singletonObject = singletonFactory.getObject(); //实际进入上个代码块的createBean(beanName, mbd, args)方法
//省略
}
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
//省略
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
//省略
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//省略
// Instantiate the bean.
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 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) {
//为了解决循环依赖问题,任何一个bean都会放入一个ObjectFactory封装
//也就是提前暴露,beanmap中此时还没有这个引用。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//省略
// Initialize the bean instance.
Object exposedObject = bean;
populateBean(beanName, mbd, instanceWrapper);//依赖注入的入口,处理注入 bean内部需要注入的属性
exposedObject = initializeBean(beanName, exposedObject, mbd);//初始化,本文不会重点介绍
return exposedObject;
}
bean
在实例化后会放到一个ObjectFactory
中,然后开始注入其他属性bean
。对应本次案例,也就是上文提到的URLService
已经初始化了。接下来要给它注入UrlService2
了。UrlService2
暂时还没有,所以首先应该实例化UrlService2
。再注入UrlService2
的相关属性,但是在注入UrlService2
的相关属性的时候,发现需要注入UrlService
。而这个UrlService 可以直接从ObjectFactory
取得,所以可以破解循环依赖问题。整个循环得以破解。下面对UrlService
中注入UrlService2
的过程分析
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
//省略
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
//主要是通过一个AutowiredAnnotationBeanPostProcessor 后置处理器 对Autowired标注的属性进行注入。当然整个方法是支持各种注入类型的,xml方式,但是这里只介绍Autowired方式。
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
}
//省略
}
进入Autowired
后置处理器分析。
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
metadata.inject(bean, beanName, pvs); //属性注入 重点
return pvs;
}
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
boolean debug = logger.isDebugEnabled();
//所有被Autowired标注的都需要依次注入
for (InjectedElement element : elementsToIterate) {
if (debug) {
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);//重点方法
}
}
}
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
//省略
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);//解决依赖注入重
点
//省略
}
//省略
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);//重新进入实例化UrlService2的过程。此过程完全类似UrlService的实例化
所以不再赘述。直接看是怎么解决循环依赖的。
}
处理UrlService2
的注入项,需要注入UrlService
,此时会beanMap
中没有,会进入实例化UrlService
的过程。但是这个过程不会执行完成。毕竟前面UrlService
的实例化过程还在栈内压着呢。所以到执行doGetBean
的方法时,Object sharedInstance = getSingleton(beanName);
就会将UrlService
返回了。所以UrlService
的第二次实例化并没有执行。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);//取到了UrlService 的封装对象
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();// 从封装对象中取得了Bean引用
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
至此UrlService2
的依赖项问题解决完毕。如果UrlService2
能处理完,自然UrlService
也能处理完。
至此整个循环依赖的原码分析完毕。