首先弄清楚Spring在这一部分涉及的一些类和接口:
BeanFactory和ApplicationContext:都是用来加载bean的,但是ApplicationContext包含了BeanFactory的所有功能并添加了许多扩展功能,比如容器后处理器、Bean后处理器、注册监听器等等。
public interface BeanFactory {
Object getBean(String name, ...) throws BeansException;
... ...
}
FactoryBean:Spring默认通过反射的方式来创建Bean实例,但是用户可以通过自己定义实现FactoryBean方法来自定义实例的创建方式。
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
ObjectFactory:通过它的getObject方法可以获取bean实例,这是用来解决循环依赖的。在循环依赖解决的代码中,它的getObject方法返回的是一个Bean的EarlyReference。
@FunctionalInterface
public interface ObjectFactory<T> {
/**
* Return an instance (possibly shared or independent)
* of the object managed by this factory.
* @return the resulting instance
* @throws BeansException in case of creation errors
*/
T getObject() throws BeansException;
}
image.png
Getbean方法:
1、 通过beanName从缓存加载bean,若为空,转2.
2、 加载创建bean:
2.1原型bean的循环依赖检查
2.2 获取beanDefinition对象,递归实例化依赖对象
2.3 根据不同的scope创建bean(默认通过反射来实例化bean,也可以通过实现FactoryBean接口来自定义实例化方式)。
从缓存中加载bean的步骤:
1、 从singletonObjects获取,没有转2
2、 从earlySingletonObjects中获取,获取不到转3
3、 从singletonFactories中获取,若获取到,则调用singleton Factory.getObject()获取bean返回并将该bean放入earlySingletonObjects中。
创建bean步骤:
1、 创建bean
2、 addSingletonFactory:这一步是解决循环依赖的关键,这样下一步填充属性的时如果发生循环依赖,那就可以从singletonFactories获取到还没创建完成的bean。
3、 填充属性
4、 其他
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName,
() -> getEarlyBeanReference(beanName, mbd, bean)); *********
}
//可以看出addSingletonFactory方法就是在singletonFactories集合中放入了该bean对应的ObjectFactory。
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory); ***********
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
Spring循环依赖解决方法:
三个缓存map:singletonObjects存放单例bean、singletonFactories存放创建Bean工厂对象、earlySingletonObjects存放创建中的Bean。
创建Bean的时候,若bean为单例且允许循环依赖的话就会提前创建一个该bean的ObjectFactory对象放入singletonFactories中(即addSingletonFactory())。所以创建其他bean的时候若依赖该bean,是可以从singletonFactories获取到该bean信息的。
网友评论