spring怎么解决循环依赖?
我们知道spring在创建bean的整个周期过程当中,会出现循环依赖问题 我们先拿出一个demo
我们创造出TestService和UserService之间有循环依赖
TestService:
package com.test.autowired.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class TestService {
//TestService 里面需要UserService 对象
@Autowired
UserService userService;
public TestService() {
System.out.println("TestService---------------无参构造器创建对象");
}
//bean创建完好后的回调
@PostConstruct
public void after(){
System.out.println("TestService------------------bean初始化完后的回调");
}
}
UserService:
package com.test.autowired.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class UserService {
//UserService 里面需要testService
@Autowired
TestService testService;
public UserService() {
System.out.println("UserService---------------无参构造器创建对象");
}
@PostConstruct
public void after(){
System.out.println("UserService------------------bean初始化完后的回调");
}
}
上面两个类 在spring启动容器加载的时候 就会出现循环依赖问题 那么我们的spring是怎么去解决的呢?
无论是先初始化完TestService还是先初始化UserService 都需要对方的属性填充 才能完成bean的整个生命周期
下面我们来看看源码
我们直接来看finishBeanFactoryInitialization(beanFactory);这个方法才是完成bean整个初始化过程
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
//首先,初始化名字为 conversionService 的 Bean。
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.
// 没什么别的目的,因为到这一步的时候,Spring 已经开始预初始化 singleton beans 了,
// 肯定不希望这个时候还出现 bean 定义解析、加载、注册。
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 开始初始化剩下的单实例bean
beanFactory.preInstantiateSingletons();
}
中间我们省略 直接看 beanFactory.preInstantiateSingletons();这个方法 我们直接进入getBean(beanName)调用的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;
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//prototypesCurrentlyInCreation 需要联系 getSingleton方法
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}else{
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;
}
代码过长 我们这里只贴出部分代码 第一次我们调用 getSingleton(beanName) 来获取bean对象 spring容器刚初始化这个时候
肯定为空 所以我们就会走进第二次调用 sharedInstance = getSingleton(beanName, () -> { try {return createBean(beanName, mbd, args);} 这个是方法的重载 那么我们就进入getSingleton这个重载方法里面
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//预创建bean对象
beforeSingletonCreation(beanName);
singletonObject = singletonFactory.getObject();
newSingleton = true;
首先我们会进入beforeSingletonCreation(beanName);
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName); }
假设我们先初始化TestSservice的bean,这个方法是将会把testService放入singletonsCurrentlyInCreation这个set里面 表示这个
beanName是将要创建的,完成beforeSingletonCreation 我们继续看 singletonObject = singletonFactory.getObject();
这里完成了一个回调 会回到我们的return createBean(beanName, mbd, args); 我们开始创建bean 我们直接进入createBean方法开面的Object beanInstance = doCreateBean(beanName, mbdToUse, args)方法
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 就是new
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);
}
return exposedObject;
上面也是贴出核心部分 首先我们的实例化出对象(注意对象bean是两个不同的概念)
//开始实例化对象 而不是bean 就是new
instanceWrapper = createBeanInstance(beanName, mbd, args); 这里通过反射实例化的是TestService对象
下面这个方法则是提供后置处理器进行处理AutowiredAnnotationBeanPostProcessor
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName)); 这里判断是否是单列 是否允许循环依赖(默认为true) 并且是否是正在创建中 由上面的分析这个earlySingletonExposure 得到的为true 则就调用下面的addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)) 将我们上面创建的对象放在二级缓存里面
下面这个方法populateBean(beanName, mbd, instanceWrapper)将是对对象进行填充 (这里就会出现自动注入 开始出现循环依赖的问题) 我们进入方法
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
}
我们省略 直接进入核心
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); 这里会调用AutowiredAnnotationBeanPostProcessor后置处理器的实现
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
我们会看到AutowiredAnnotationBeanPostProcessor的postProcessProperties填充属性的时候回调用metadata.inject(bean, beanName, pvs); 自动注入的方法 我们进入inject()方法
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
......
.....
...
我们可以看我们的bean工厂处理这层依赖关系 我们看value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); 点进去 我们发现我们又回到了大家数据的DefaultListableBeanFactory这个类中
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
直接看最后处理方法result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
点进去 我们找到最后的
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
} 到此你会发现 我们又进入了beanFactory.getBean(beanName); getBean的方法 但是这里的是获取带有注解的bean 也就是我们这里的userService 这样我们又回到原点去getSingtonObject().....等等一系列的操作
就上面做个总结:
假如我们a注入了b b也注入了a 那么spring容器初始化的时候 假如是先初始化A,初始化的过程中在AbstractAutowireCapableBeanFactory的doCreateBean方法中先会创建a的对象(利用反射)创建完对象后 给该对象填充属性,这时候会发现b这个对象并不存在,那么根据判断调用AutowiredAnnotationBeanPostProcessor后置处理器去处理b的bean的初始化的过程 这个时候就会来初始化b 初始化b的整个过程中 发现需要a对象 由于前面我们已经创建了a对象放在了二级缓存当中,这里b就可以直接去取出来 完成对应的初始化工作, 等b的bean初始化完成之后a陆续完成对应的初始化工作。
我们暂时对着源码分析到这里 当然这里有很多细节 需要我们对着源码断点分析
上一篇: DOM解析示例
下一篇: 表格 文本框 按钮个人笔记