本文档基于Spring 5.1.4.RELEASE版本进行编写。
- 下文很多地方出现
默认配置
,有点抽象,但大概指的就是例如:不自己编写ApplicationContext
的子类、不手动注册BeanDefinition
这一类的操作。 - 下文很多地方在if判断的括号后写的注释表示的是括号内的条件怎样才会成立
- 下文都是基于本文展示的调用链进行说明的。
关于循环依赖、动态代理可以搜索补充-{0}直接跳转过去,懒得搞目录了。
在阅读过程中,如果遇到循环依赖的注释,可以先不管,在了解循环依赖时再看也不迟,有写的
1. getBean(String) & doGetBean(String, Class<T>, Object[], boolean)
getBean(String)
方法负责bean的实例化以及内部参数的注入等初始化操作。
本节主要完成了
dependsOn
的处理,dependsOn
循环依赖的处理具体见 3.1 小节。
bean的创建过程交由之后的调用链完成。
// AbstractBeanFactory
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// AbstractBeanFactory
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 在本段代码中将用数字表明默认情况一个单例Bean被创建的过程
// 1.找到最终的 beanName, 会对 FactoryBean、配置了别名的bean进行名称处理,得到最终的 beanName
final String beanName = transformedBeanName(name);
Object bean;
// 2.从bean的单例缓存中获取值 (如果不为null,代表bean已经创建过/正在在创建中;但相反如果为null,不一定没创建过)
// 在解决属性的循环依赖中发挥了重要作用
Object sharedInstance = getSingleton(beanName);
// 3.判断bean是否已经创建过/正在在创建中
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 { // 进入这里时,bean可能已经在创建了
// 如果一个bean在创建期间重复进入这里,代表出现了属性的循环依赖,见3.2小节
// 4.判断当前原型 bean 是否正在创建中 (这个是对多例的处理)
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 5.判断有没有父容器(在示例代码中,内部IOC容器是没有父容器的,Application容器只是持有内部IOC容器)
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 有父容器且当前容器内没找到这个bean的元数据
// 就尝试在父容器中创建bean
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);
}
}
// 6.判断typeCheckOnly是否为true (由上层调用者传入,提供的所有getBean方法传入的都是false)。
// 如果为 true 代表获取实例是为了进行类型检查,而不是为了实际使用,
// 有一种情况会传入true,调用AbstractBeanFactory#isTypeMatch方法,且目标bean实现了FactoryBean时。
if (!typeCheckOnly) {
// 7.标记bean为已创建,添加到AbstractBeanFactory的alreadyCreated集合中,并把bean的元数据删除。
markBeanAsCreated(beanName);
}
try {
// 8.获取BeanDefinition,并检查BeanDefinition是否是抽象的
/*
* RootBeanDefinition 这里简单说一下它跟什么有关系,<bean/>的parent属性,它在Spring有同名对应的类。
* 我们配置的bean在被解析时,首先会被解析为GenericBeanDefinition对象实例,但是下面的getMergedLocalBeanDefinition方法调用后
* 都会转变为RootBeanDefinition,只不过有没有parent属性决定了它们的处理逻辑的不同。
* 可以理解为,RootBeanDefinition是一个和可能存在的parent合并而来的产物。
* !关于<bean/>的parent属性使用示例:
* <bean id="parent" class="com.x.x.Parent"> 如果 Parent 类里没有定义 name 属性,那么可以给标签添加 abstract=true 或者 lazy-init=true 来避免容器启动失败。
* <property name="name" value="foo"/>
* </bean>
* <bean id="child" class="com.x.x.Child" parent="parent"> Child类中必须有 name 属性才行
* <property name="age" value="18"/>
* </bean>
* Child 会继承 name 属性的值, 但是在Java代码层面2个类并没有关系,一般这情况都是用来当模板减少配置的。
*
* MergedBeanDefinition 没有同名对应的类,但在getMergedLocalBeanDefinition方法中,会把转变后的RootBeanDefinition
* 当成MergedBeanDefinition,存放到AbstractBeanFactory类的mergedBeanDefinitions属性中
*/
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 如果<bean abstract=true/>,而且尝试主动通过了doGetBean方法实例化,到下面这个方法就会抛出BeanIsAbstractException异常。
// 保证了抽象的bean不可能完成实例化。
checkMergedBeanDefinition(mbd, beanName, args);
// 9.优先创建当前bean所依赖的bean,与<bean/>标签中的depends-on属性有关
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 检测双向以来,在这一步执行时,见 1.6 小节
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 每个depends-on都要注册为双向依赖关系,用于支持isDependent方法进行循环依赖检测,见 3.1 小节
registerDependentBean(dep, beanName);
try {
getBean(dep); // 对依赖的的bean先进行处理。
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 创建bean实例
if (mbd.isSingleton()) { // 单例
// 10.使用传入的lambda函数创建bean (实例化 + 初始化)
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;
}
});
// 11.如果当前bean是FactoryBean,尝试调用FactoryBean中的getObject()获取目标结果。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// ... 省略了多例以及其它Scope的创建方式
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 12.保证获取的bean实例为所需的类型,如果不一致,需要通ConversionService服务转换
// 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;
}
1.2. getSingleton(String) & getSingleton(String, boolean)
这个方法要配合属性的循环依赖来看,如果还没看到先跳过本节,关于属性的循环依赖见 3.2 小节。
/** 单例对象的缓存: Key是beanName Value是bean对象实例. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 早期的单例对象的缓存: Key是beanName Value是bean对象实例. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** 单例的创建方式的缓存: Key是beanName Value是一个lambda函数,代表了bean应该如何实例化. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// DefaultSingletonBeanRegistry
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
// DefaultSingletonBeanRegistry
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 提前说明,这里的this指的就是内部IOC容器,是一个DefaultListableBeanFactory实例对象
// 先尝试从单例缓存中读取,如果读取到了直接返回
// 要是能读取到,代表当前bean实例已经创建完成。
Object singletonObject = this.singletonObjects.get(beanName);
// 如果缓存中没有,且当前的 bean 正在创建的过程中
// 要是符合这个条件,就代表存在bean的创建过程中存在属性间的循环依赖。
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// 如果不为空,代表allowCircularReferences为true,也就是说允许属性之间的循环依赖。
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 从singletonFactories晋升到earlySingletonObjects中。
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
1.3. getSingleton(String, ObjectFactory)
/** 按注册顺序存放着已经注册的单例的name */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
/** 当前正在创建的bean的名称集合. */
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
/** Names of beans currently excluded from in creation checks. */
private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// DefaultSingletonBeanRegistry
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) { // 缓存中没有
// ------------------------- singletonsCurrentlyInDestruction的验证 -------------------------
// 判断单例集合是否正在销毁,如果为true意味着IOC容器刷新失败,或者应用正在关闭。
/*
* 在之前说过的代码中有2个地方会把这个值设置为true
* 第1个地方:AbstractApplicationContext#refresh() 中的obtainFreshBeanFactory()逻辑里
* 第2个地方:AbstractApplicationContext#refresh() 的catch块内调用的destroyBeans()
*/
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 + "'");
}
// --------------------------------------- 执行单例创建前的逻辑 ---------------------------
/* 如果不在 inCreationCheckExclusions 集合中,则添加到 singletonsCurrentlyInCreation 集合中,如果集合中已经存在就抛出循环依赖异常
* singletonsCurrentlyInCreation 集合标记了当前正在创建的bean,在循环依赖的确定中发挥作用。
*
* 这行代码是属性循环依赖检查的重要逻辑点,用以在不允许属性循环依赖时抛出异常,见 3.2 节。
*/
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// --------------------------------------- 创建单例 ---------------------------
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
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;
}
// --------------------------------------- 执行单例创建后的逻辑 ---------------------------
// 如果不在 inCreationCheckExclusions 集合中,则从 singletonsCurrentlyInCreation 集合中移除出去
// 在 singletonsCurrentlyInCreation 集合中一进一出代表bean的创建完成。
afterSingletonCreation(beanName);
}
// 判断是刚创建的单例对象 还是 从缓存中拿出来的
if (newSingleton) { // 是刚创建的
// 把刚创建的bean放到缓存对象里 并 对其他集合进行数据处理,在解决属性的循环依赖中发挥了重要作用,见 3.2 节。
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
// DefaultSingletonBeanRegistry
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);
}
}
1.3.1. beforeSingletonCreation & afterSingletonCreation
// DefaultSingletonBeanRegistry
protected void beforeSingletonCreation(String beanName) {
// 如果不在 inCreationCheckExclusions 集合中,则添加到 singletonsCurrentlyInCreation 集合中
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
// 见 3.2 节
throw new BeanCurrentlyInCreationException(beanName);
}
}
// DefaultSingletonBeanRegistry
protected void afterSingletonCreation(String beanName) {
// 如果不在 inCreationCheckExclusions 集合中,则从 singletonsCurrentlyInCreation 集合中移除出去
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
1.3.2. createBean(String, RootBeanDefinition, Object[])
// 只看lambda里面
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args); // 创建bean
}
catch (BeansException ex) {
// 实例化过程出现异常 销毁bean实例化过程中的一切相关项
destroySingleton(beanName);
throw ex;
}
});
// AbstractAutowireCapableBeanFactory
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ... 日志打印 "Creating instance of bean '" + beanName + "'"
RootBeanDefinition mbdToUse = mbd;
// ----------------------------------------- 解析出要实例化的Class ----------------------------------
// 将配置文件中<bean>标签的class属性指定的符号引用加载为一个类,在一般情况下会直接把这个类放入mbd中。
// 如果进入下面的if里面就代表不一般。
// 如果这个过程中出现异常则会抛出 CannotLoadBeanClassException 异常。
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
/* 如果你使用了SpEL表达式配置<bean>标签的class属性,会进入这里。
* 例如:<bean id="x" class="#{'com.example.demo.springtest.base.OutputServiceImpl'}"/>
*
* 针对于进入到这里的bean,其原始的BeanDefinition的beanClassName是一个表达式显然是不方便使用的
* 这里会复制原始的BeanDefinition,并设置BeanClass,作为即将使用的RootBeanDefinition。
*/
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// --------------------------------------- 处理 MethodOverride ----------------------------------
// Prepare method overrides.
try {
// 这个是对 <lookup-method/> 和 <replaced-method/> 标签的简单标记
// 方法内部对元数据内的 MethodOverride进行了setOverloaded(false)行为。
// 这两个标签都会被处理成MethodOverride对象,在实例化对象时,如果有MethodOverride,会使用CGLIB生成代理类,见AbstractAutowireCapableBeanFactory#createBean。
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
// --------------------------------- 尝试靠BeanPostProcessors来生成代理类 ----------------------------
try {
// 给BeanPostProcessors一个返回目标类的代理实现的机会,如果返回了代理类,那就不需要再实例化bean了,见 4.1 小结
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);
}
// --------------------------------------- 执行创建bean的行为 ---------------------------------------
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) {
// 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);
}
}
1.3.2.1. doCreateBean(String, RootBeanDefinition, Object[])
完成bean的实例化与初始化(填充属性、调用Aware相关方法等)
// AbstractAutowireCapableBeanFactory
/** 还没有实例化完成的FactoryBean的缓存: FactoryBean name to BeanWrapper. */
private final ConcurrentMap<String, BeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>();
// AbstractAutowireCapableBeanFactory
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);
}
// ---------------------------------------- 实例化bean --------------------------------------
// 这里是为了确认一下是不是还没有实例化结束的FactoryBean
if (instanceWrapper == null) { // (如果)不是
// 创建bean实例,返回的BeanWrapper包含有已经实例化的bean实例,但还没有进行属性填充
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance(); // 实例化的bean
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// ------------------------------- 应用BeanDefinitionPostProcessor ----------------------------
// 调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法。
// 对bean中使用的注解进行解析与检查(例如@Autowired、@Resource、@PostConstruct、@PreDestroy等),
// 方便后续参数注入等合适的时机使用。
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) { // (如果)还没有被BeanDefinitionPostProcessor处理过
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;
}
}
// ---------------------------------------- 准备处理循环依赖的数据 -------------------------------------
/*
* 1.当前要实例化的bean是单例
* 2.内部IOC容器允许循环引用
* 如果内部IOC容器是非自定义的,那么总是为true的,可以手动设置。
* 3.当前bean正在创建 (检测是否在singletonsCurrentlyInCreation集合中)
* 在上层调用者getSingleton(String, ObjectFactory)中调用createBean之前已经把当前bean添加到了这个集合中。
* 满足这3点就把当前bean放入到singletonFactories列表中,让程序支持bean内属性的循环引用。
*/
// 如果当前bean是单例,默认情况下 earlySingletonExposure 的值就为 true,后面两个判断项在当前调用链中
// 可以忽视,三个判断缩减为一个判断,也就是只要是单例这里就为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");
}
// getEarlyBeanReference方法内部的逻辑涉及到了代理类的创建,见 4.3 小结。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// ------------------------------------- 初始化bean实例 ----------------------------------------
// 之前是bean的实例化工作(创建实例对象),这里是进行对bean实例进行初始化(设置属性)
Object exposedObject = bean;
try {
// 填充属性
populateBean(beanName, mbd, instanceWrapper);
// 调用bean的InitMethods、处理bean的其他注解等
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);
}
}
// 到这里,当前bean的实例化与初始化工作已经完成了
if (earlySingletonExposure) {
// 主要目的是为了尝试从earlySingletonObjects中拿到数据
Object earlySingletonReference = getSingleton(beanName, false);
// 想让这个成立,可以写个Bean,里面写2+个自身的依赖的属性。
if (earlySingletonReference != null) { // (如果)不为空
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// 这里两者不相等,是因为在循环引用的逻辑中,BeanPostProcessor的初始化前/后的后处理可能对bean的实例发生变动。
// 这种情况是应该尽量避免的,自定义BeanPostProcessor的逻辑时应该注意一下
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 {
// (有前提条件的)尝试注册到容器的disposableBeans集合中,用于在必要时执行相关的自定义销毁逻辑,下面有说明。
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
1.3.2.1.1. createBeanInstance(String, RootBeanDefinition, Object[])
这个方法的功能是:选用合适的方式创建bean实例。
// AbstractAutowireCapableBeanFactory
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 上面已经调用过这个方法了,这里直接取出来RootBeanDefinition对象里的BeanClass
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 1.类存在 2.类的访问修饰符不包含public 3.不允许非公开的访问,满足这3点就会进入 if 代码块然后报异常。
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// ----------------------------------- 使用instanceSupplier实例化bean -------------------------------
// 这是一种自定义实例化过程的方式,下面有使用说明,方法内部很简单不进行说明
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// ----------------------------------- 使用factory-method实例化bean ---------------------------
// 这是一种自定义实例化过程的方式,下面有使用说明,方法内部很简单不进行说明
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// ----------------------------------- 重新创建同一bean时的快捷方式 -----------------------------
// 使用factory-method、BeanPostProcessor机制、默认构造的首选构造函数这3种情况时,都是要解析构造函数或工厂方法的,重复的不断解析显然是性能亏损的,所以可以缓存起来下次直接使用,所计叫快捷方式。
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// resolvedConstructorOrFactoryMethod 和 constructorArgumentsResolved 属性的赋值在
// ConstructorResolver的 instantiateUsingFactoryMethod 和 autowireConstructor 两个方法中都存在
// 见 ConstructorResolver#storeCache
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
// 通过autowire构造函数实例化bean。
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 与这个方法最后一行逻辑一样。
return instantiateBean(beanName, mbd);
}
}
// ------------------------------ 使用BeanPostProcessor机制实例化bean ----------------------------
// 使用BeanPostProcessor机制获取bean的构造函数,然后使用构造函数进行实例化bean。
/*
* 见 AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors
* 其中对添加了@Lookup注解的方法、添加了@Autowired的构造函数有相应的处理,见下文
*/
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 1.构造函数不为null
// 2.AutowireMode为constructor -> 和<bean>标签的autowire属性有关
// 3.有构造函数参数值(ConstructorArgumentValues) -> 和<bean>标签下的子标签<constructor-arg>有关
// 4.args = null || args.length == 0 -> 本文展示的调用链的逻辑里,是一直为null的
// 只要满足其中任意一个,就能进入if代码块
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// ----------------------------- 使用默认构造的首选构造函数实例化bean ------------------------------
// RootBeanDefinition的这个方法会返回null
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// ----------------------------- 使用默认的方式(无参构造函数)实例化bean ------------------------------
// 上面的那么多种形式都是特殊的实例化方式,只有这个是默认的,默认使用无参构造函数。
// 如果当前bean使用了<lookup-method/> 或 <replaced-method/>,Spring会为当前bean创建CGLIB子类,并返回子类的实例化对象,而不是原始的类的。
// 见CglibSubclassingInstantiationStrategy#instantiate(Constructor, Object[])
return instantiateBean(beanName, mbd);
}
1.3.2.1.1.1. InstanceSupplier的使用
这个属性在BeanDefinition
的多个实现类中都可以用,它提供一种仍受内部IOC容器
管控的独特的实例化bean的方式。
它允许用户自定义bean的实例化逻辑,不需要再使用默认情况下通过反射去实例化bean的做法。
// 示例代码
public static void main(String[] args) {
GenericBeanDefinition helloServiceBeanDefinition = new GenericBeanDefinition();
helloServiceBeanDefinition.setBeanClassName("com.example.demo.springtest.base.HelloServiceImpl");
// 自定义bean的实例化过程
helloServiceBeanDefinition.setInstanceSupplier(() -> {
HelloServiceImpl helloService = new HelloServiceImpl();
helloService.setContent("自定义实例化逻辑");
return helloService;
});
// 交由Spring完成内部属性的注入(DI)
MutablePropertyValues propertyValues = helloServiceBeanDefinition.getPropertyValues();
propertyValues.addPropertyValue("outputService", new RuntimeBeanReference("outputService"));
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml"}, true, null);
// 这里注意,要让refresh=true,否则内部IOC容器还没有创建就注册BeanDefinition会报错
((BeanDefinitionRegistry) ac.getBeanFactory()).registerBeanDefinition("helloService1", helloServiceBeanDefinition);
// bean的获取与方法调用
HelloService helloService = ac.getBean("helloService1", HelloService.class);
helloService.sayHello();
}
1.3.2.1.1.2. factory-method的使用
可以通过配置
<bean>标签的factory-method属性
来使用,它也提供一种仍受内部IOC容器管控的独特的实例化bean的方式,允许用户自定义bean的实例化逻辑。
public class ServiceFactory {
// 非静态方法
public XXService createService() { return new XXService(); }
// 静态方法2
public static XXService createStaticService2(String arg) { return new XXService(arg); }
// 静态方法1
public static XXService createStaticService() { return new XXService(); }
}
<!-- 非静态的方式:-->
<bean id="serviceFactory" class="a.b.c.ServiceFactory" />
<bean id="service1" factory-bean="serviceFactory" factory-method="createService"/>
<!-- 静态的方式1: (mbd参数指定类) -->
<bean id="service2" class="a.b.c.ServiceFactory" factory-method="createStaticService"/>
<!-- 静态的方式2: (工厂对象本身使用依赖注入配置的实例变量) -->
<bean id="service3" class="a.b.c.ServiceFactory" factory-method="createStaticService2">
<constructor-arg value="abc"/> <!-- 如果要传依赖对象进入 value -> ref -->
</bean>
1.3.2.1.1.3. 使用BeanPostProcessor机制获取bean的构造函数
默认情况下只会被
AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors
处理。
使用
@Autowired
注解构造函数这种情况比较罕见,当类中有多个构造函数时可以使用这个机制。
1.只有无参构造函数,返回null。
2.有无参构造函数也有有参构造函数,不使用@Autowired
,返回null。
3.只有一个有参构造函数,不使用@Autowired
,返回有参构造函数,但是入参有严格要求,必须是可以被容器管理的。
4.有多个有参构造函数,不使用@Autowired
,返回null,之后抛出异常。
5.有任意数量构造函数,使用一个@Autowired
,返回被注解的那个构造函数,入参必须是可以被容器管理的。
// 使用实例
@Service
public class TestService {
private MessageSource messageSource;
public TestService() {}
@Autowired
public TestService(MessageSource messageSource) {
this.messageSource = messageSource;
}
}
同时这个方法中也有对
@Lookup
注解的处理逻辑。
@Lookup
和<bean>标签的lookup-method属性
是等效的。
@Lookup Annotation in Spring
public class A {
public void test() { System.out.println(getA()); }
public B getB() { return null; }
}
public class B() {}
<bean id="a" class="a.b.c.B" scope="prototype"/>
<bean id="b" class="a.b.c.A">
<lookup-method name="getB" bean="a"/>
</bean>
@Test
public void testLookup() {
A a = this.context.getBean(A.class);
a.test();
}
1.3.2.1.2. addSingletonFactory & getEarlyBeanReference
// DefaultSingletonBeanRegistry
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
// 传入的singletonFactory是一个lambda函数,它内部的逻辑涉及到了代理类的创建,很值得注意。
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
/* 这个判断如果成立,代表当前bean还没有完成实例化与初始化这整个步骤,
* 当前方法在由createBean(String, RootBeanDefinition, Object[])产生的调用链过程内,
* 也就是说在执行这个方法时,bean已经实例化完成了,但还没有完成赋值等后续操作。
* 只有完成这个调用链,那么这个bean才会被放入singletonObjects中。
*/
if (!this.singletonObjects.containsKey(beanName)) { // (如果)单例对象缓存中不包含当前bean
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
至于getEarlyBeanReference
方法,它涉及到了代理类的创建,这里不进行代码展示,它的说明在下文 4.3 小节。
1.3.2.1.3. populateBean(String, RootBeanDefinition, BeanWrapper)
这个方法的功能是:向bean的实例对象内填充属性值。
// AbstractAutowireCapableBeanFactory
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ------------------------------------------ 先行的校验 -------------------------------------------
// 一个先行的校验,确保要被填充的的实例对象存在。(BeanWrapper持有bean实例对象)
if (bw == null) {
if (mbd.hasPropertyValues()) { // (如果)bean的元数据设置有属性值
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else { // 没有属性值
// Skip property population phase for null instance.
return;
}
}
// -------------- 执行 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation -------------
// 在(给bean实例)设置属性前,给InstantiationAwareBeanPostProcessor这个类型的BeanPostProcessor一个机会,让它们修改bean的状态。
// 例如,这可以用来支持字段注入的方式。
boolean continueWithPropertyPopulation = true;
// 1.类不是桥接的 2.有InstantiationAwareBeanPostProcessor类型的BeanPostProcessor 满足这两点就会进入 if 代码块
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor);
// 基于默认提供的实现,下面的if代码块不会进入。在这里就可以靠自定义BeanPostProcessor,完成自定义方式的属性的注入行为。
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false; // 标记不再需要后续的属性注入行为。
break;
}
}
}
}
// 检测还是否需要继续属性注入操作
if (!continueWithPropertyPopulation) { // 不需要
return;
}
// bean元数据中定义的属性,和<property>标签有关,表示所有的property指定的属性。
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// ------------------------------------- 处理<bean>标签的autowired属性 --------------------------------
// 会根据指定的方式(byName/byType)从内部IOC容器中获取到属性的实例对象,然后再设置给BeanDefinition
// getResolvedAutowireMode() 方法的执行结果和<bean>标签的autowired属性有关
// 如果值为byName则代表根据名称注入;如果值为byTime则代表根据类型注入,只要满足一个条件则进入 if 代码块。
// 默认情况下为0,也就是说不会进入 if 代码块,这个属性好像在老版本中有使用过。
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// getDependencyCheck()的返回值和<bean>标签的dependency-check属性有关,高版本spring已经不允许xml配置它了。
// 默认情况为0,也就是DEPENDENCY_CHECK_NONE,所以这里会得到false。
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
// ------------------------------------- 给使用注解方式的属性注入值 ----------------------------------
// 调用InstantiationAwareBeanPostProcessor#postProcessProperties时完成注入操作
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) { // 有InstantiationAwareBeanPostProcessor类型的Bean后处理器
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 对使用注解的属性进行值注入(这些值不会放到PropertyValues里),值得关注的实现类有
// AutowiredAnnotationBeanPostProcessor -> 给@Autowired注解的属性注入值
// CommonAnnotationBeanPostProcessor -> 给@Resource注解的属性注入值
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) { // 内部的逻辑默认情况下不会被执行。(大概这块的逻辑已经被放弃了)
// 在bean元数据没有配置属性时,对bean内必须注入的属性进行处理。(例如@Required注解)
if (filteredPds == null) {
/* 过滤出需要依赖检查的属性。
* 1.通过反射获取BeanClass的属性
* 2.然后去除掉 忽略的依赖关系类型 和 在忽略的依赖关系接口上存在Setter方法的属性
* -前者见AbstractAutowireCapableBeanFactory中的ignoredDependencyTypes属性,
* 默认情况下,它是没有值的,可以手动向内部IOC容器中添加,
* 手动添加方式:重写refresh()中调用的postProcessBeanFactory方法,然后手动添加。
*
* -后者见AbstractAutowireCapableBeanFactory中的ignoredDependencyInterfaces属性,
* 默认情况下,它有被设置值,见refresh()中调用的prepareBeanFactory方法。
* 3.得到最后的结果。(如果允许缓存就缓存一下)
*/
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 比较特殊的是 RequiredAnnotationBeanPostProcessor,这个类中有对@Required注解的处理
// 但是现在这个类和这个注解都已经弃用,默认情况下也不会被处理。
// 如果想要恢复使用,可以看下面给出示例。
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
// ------------------------------ 处理<bean>标签配置的dependency-check相关内容 ----------------------
// 根据dependency-check指定的模式进行对参数的验证
if (needsDepCheck) { // 这个代码块默认情况下也不会执行
if (filteredPds == null) {
// 这个方法在上面有说过,过滤出需要依赖检查的属性。
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 按照<bean>标签配置的dependency-check指定的模式进行验证
checkDependencies(beanName, mbd, filteredPds, pvs);
}
// ---------------------------------- 对PropertyValues中的属性进行注入 -------------------------------
// 这种方式不会对使用了@Autowired、@Resource这类注解的属性进行值的注入,它们的值注入在上面就已经完成了。
// 也就是在 ‘给使用注解方式的属性注入值’ 这一块代码内完成的。
if (pvs != null) {
// 把PropertyValues中的内容填充到bean的实例对象内。
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
1.3.2.1.3.1. 恢复@Required注解的做法
// xml配置
<bean id="helloService" class="a.b.c.HelloServiceImpl"/> // 不提供任何参数
// bean
class HelloServiceImpl implements HelloService {
// ... 其他属性
private OutputService outputService;
//... 其他逻辑
@Required // 必须的的参数
public void setOutputService(OutputService outputService) {
this.outputService = outputService;
}
}
// 自定义的容器实现
class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
public MyClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(configLocations, refresh, parent);
}
@Override
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 恢复@Required注解的作用
beanFactory.addBeanPostProcessor(new RequiredAnnotationBeanPostProcessor());
super.registerBeanPostProcessors(beanFactory);
}
}
// 测试
@Test
public void test() {
ApplicationContext ac = new MyClassPathXmlApplicationContext(new String[]{"spring-config.xml"}, true, null);
HelloService helloService = ac.getBean(HelloService.class);
helloService.sayHello();
}
1.3.2.1.3.2. 关于property属性对引用的赋值
这里不想展示完全的逻辑,很多都不用关心,主要展示一下对于
RuntimeBeanReference
类型参数的解析以及向对象内填充值,并且简单说明为什么默认情况下两个bean中以参数形式出现的循环依赖不会出现问题。
AbstractAutowireCapableBeanFactory#populateBean(String, RootBeanDefinition,BeanWrapper)
AbstractAutowireCapableBeanFactory#applyPropertyValues(String, BeanDefinition, BeanWrapper, PropertyValues)
BeanDefinitionValueResolver#resolveValueIfNecessary(Object, Object)
BeanDefinitionValueResolver#resolveReference(Object, RuntimeBeanReference)
AbstractPropertyAccessor#setPropertyValues(PropertyValues)
AbstractPropertyAccessor#setPropertyValues(PropertyValues, boolean, boolean)
AbstractNestablePropertyAccessor#setPropertyValue(PropertyValue)
// BeanDefinitionValueResolver
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
// 对应<property ref=""/>
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
// .... 其他类型的属性处理
}
// BeanDefinitionValueResolver
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
Object bean;
String refName = ref.getBeanName();
refName = String.valueOf(doEvaluate(refName));
if (ref.isToParent()) {
if (this.beanFactory.getParentBeanFactory() == null) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Can't resolve reference to bean '" + refName +
"' in parent factory: no parent factory available");
}
// 尝试从父容器中获取
bean = this.beanFactory.getParentBeanFactory().getBean(refName);
}
else {
// 尝试从当前容器中获取,主要就是关注这里,属性的值的获取方法。
bean = this.beanFactory.getBean(refName);
// 注册双向依赖关系。
this.beanFactory.registerDependentBean(refName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
}
catch (BeansException ex) {
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
}
}
// AbstractAutowireCapableBeanFactory
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// ... 省略逻辑
// Set our (possibly massaged) deep copy.
try {
// 通过反射,把值填充进去
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
关于属性的循环依赖最核心的就是在这段代码里对getBean(refName)
方法的调用。
关于属性的循环应用在之后会有补充,见 3.2 小节。
1.3.2.1.4 initializeBean(String, Object, RootBeanDefinition)
这个方法做了以下几件事
1.调用实现了Aware
这一类接口的bean内重写的方法。
2.执行BeanPostProcessor#postProcessBeforeInitialization
方法。
3.执行InitializingBean
和init-method
相关的内容。
4.执行BeanPostProcessor#postProcessAfterInitialization
方法
// AbstractAutowireCapableBeanFactory
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// -------------------------------- 执行实现了Aware接口的bean内的相关方法 ------------------------------
// Aware这东西太简单了不细说了,就上层向下层的主动数据传递,自己可以实现一个BeanFactoryAware测试一下。
if (System.getSecurityManager() != null) {
// 这个看上篇文章,里面有说 AccessController
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// ------------------------ 执行BeanPostProcessor#postProcessBeforeInitialization方法 ----------------
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// --------------------------------- 执行InitMethod相关的方法 --------------------------------
/*
* 这个东西有2种配置方式
* 1.让bean Class实现InitializingBean接口,重写其中的方法。
* 2.在<bean>标签中配置init-method属性。
*
* 这两种的使用方法在Spring MVC框架的启动过程中说过,在正确的使用方式下,两者可以同时生效,且前者先于后者执行。
*/
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// ------------------------ 执行BeanPostProcessor#postProcessAfterInitialization方法 ----------------
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
1.3.2.1.5. registerDisposableBeanIfNecessary
如果需要,将当前bean注册到容器的
disposableBeans
集合中,用于在必要时执行相关的自定义销毁逻辑。
例如:实现了DisposableBean
或AutoCloseable
接口;设置了destory-method
属性等,这类bean就是需要这样处理的。
// AbstractBeanFactory
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { // 单例 且 有自定义的销毁逻辑
// 只看单例,其他的Scope不考虑
if (mbd.isSingleton()) { // 单例
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else { // 其他Scope的处置
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
// AbstractBeanFactory
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
// 后面那个判断的逻辑太长了,写在了下面
// 总之,这里就是判断这个bean有没有自定义的销毁逻辑。
return (bean.getClass() != NullBean.class &&
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}
// DefaultSingletonBeanRegistry
public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean);
}
}
requiresDestruction(Object, RootBeanDefinition) 方法内的判断的逻辑格式化后的样子
(
DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
(
hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors())
)
)
先说第一个判断 DisposableBeanAdapter.hasDestroyMethod(bean, mbd)
1.如果实现了DisposableBean或者AutoCloseable,返回true
2.如果元数据中配置了destory-method,也就是说在xml配置实现中<bean>标签里面有没有destory-method属性,没有就返回false
2.1 如果有且值是一个正常的方法名,返回true
2.2 如果有但值是'(inferred)',就得看类里有没有close或者shutdown方法
只要三条线任意一条为true,那第一个判断条件就是true
再说第二个判断 hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors())
3.有实现了DestructionAwareBeanPostProcessor接口的BeanPostProcessor,返回true,默认情况就有。
4.有合适的,正好能处理现在这个bean的。(DestructionAwareBeanPostProcessor接口默认情况下都会合适,就看实现类有没有重写)
4.1 ApplicationListenerDetector -> 如果bean实现了ApplicationListener,返回true
4.2 InitDestroyAnnotationBeanPostProcessor -> 如果bean class内有使用了@PreDestroy注解的方法,返回true
4.3 ScheduledAnnotationBeanPostProcessor -> 如果bean class内有使用了@Scheduled注解的方法,返回true
只有当 3 和 4中的任意1个 同时为 true 时 第二个判断条件才会为 true
第一个判断和第二个判断任意一个为true,最终结果就会为true
1.4. getObjectForBeanInstance(Object, String, String, RootBeanDefinition)
不论是哪种获取bean实例化的方式,最终都会执行到这个方法。
这个方法它是对FactoryBean
类型的bean的处理,这种类型的bean实例化完成后得到的是一个工厂
,
使用者在使用FactoryBean
时,想要的不是这个工厂
,而是通过工厂内的getObject()
方法自定义的逻辑创建的对象实例。
而这个方法就是用来调用FactoryBean#getObject()
的,如果是单例的话,还会把执行结果缓存起来。
// AbstractAutowireCapableBeanFactory 类是实现了getObjectForBeanInstance方法的最底层的类,所以先找到 AbstractAutowireCapableBeanFactory 中的实现
// AbstractAutowireCapableBeanFactory
private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");
// FactoryBeanRegistrySupport
/** 被FactoryBean创建出来的单例对象 的缓存: FactoryBean name to 单例对象. */
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
// AbstractAutowireCapableBeanFactory
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// ------------------------------------------------------ 存储bean之间的依赖关系 -----------------------------------------------------
// 获取当前已经创建的bean的名称
// 见AbstractAutowireCapableBeanFactory#obtainFromSupplier
String currentlyCreatedBean = this.currentlyCreatedBean.get();
if (currentlyCreatedBean != null) {
// 注册bean之间的双向依赖关系,用于检测循环依赖
registerDependentBean(beanName, currentlyCreatedBean);
}
// 调用 AbstractBeanFactory 里面的 getObjectForBeanInstance 方法
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
// AbstractBeanFactory
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 对于没有实现FactoryBean的bean来说,进来走个过场什么都不做就直接返回了。
if (BeanFactoryUtils.isFactoryDereference(name)) { // bean的名称以字符&开头
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// bean的名称以字符&开头,按照约定来说这个bean是一个FactoryBean,如果bean name以字符&开头但没有实现FactoryBean,直接抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// 现在我们有了bean实例,它可以是普通bean或FactoryBean。
// 如果它是一个FactoryBean,我们就用它来创建一个bean实例,除非调用者真的想要一个对工厂的引用。
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { // 不是FactoryBean类型的bean
return beanInstance;
}
Object object = null;
if (mbd == null) {
// 尝试从factoryBeanObjectCache这个缓存数据集中拿到数据。
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 大体步骤:
// 1.使用 FactoryBean 中定义的 getObject() 来获取对象实例,
// 2.根据 !synthetic 的结果,判断要不要执行所有 BeanPostProcessor的postProcessAfterInitialization 方法,为true就执行。
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
1.5. registerDependentBean(String, String)
注册双向依赖关系。
/** 记录了bean之间的依赖关系,存储的都是beanName */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** 记录了bean之间的'被'依赖关系,存储的都是beanName */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
// AbstractAutowireCapableBeanFactory
public void registerDependentBean(String beanName, String dependentBeanName) {
// 获取规范的名称,对别名的处理,最终结果是能代表这个bean的beanName
String canonicalName = canonicalName(beanName);
// 以A类中依赖了B为例进行说明
// ----------------------------------------- 处理依赖关系 -------------------------------------------
synchronized (this.dependentBeanMap) {
// A类的名称作为Key,B类的名称作为Value记录下来,注意Value是一个集合
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
// ----------------------------------------- 处理被依赖关系 -------------------------------------------
synchronized (this.dependenciesForBeanMap) {
// B类的名称作为Key,A类的名称作为Value记录下来,注意Value是一个集合
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
1.6. isDependent(String, String)
用于检查
depends-on
属性的循环依赖,确认传入的两个bean之间是否存在依赖关系。
要注意该方法的执行时机,以及它之后的registerDependentBean(dep, beanName)
。
这里结论先行,用3个示例展示这个循环依赖的执行逻辑,可以用笔在纸上画出来看看。
第一个示例:A depends-on B、B depends-on A (A和B之间的循环依赖)
1.当首次getBean(A)时,方法的入参为(A, B),逻辑里dependentBeanMap.get(A)为null,所以执行判断2的返回语句(false),在方法外把 B->[A] 这个关系存放到dependentBeanMap中,随后调用getBean(B)。
2.当首次getBean(B)时,方法的入参为(B, A),逻辑里dependentBeanMap.get(B)获取到[A],随后在判断3的比对中发现依赖A存在于集合的返回结果中,所以执行判断3的返回语句(true),在方法外抛出循环依赖的异常。
在第一个例子中,值得注意的是执行第一步时,A是当前bean,B是A所依赖的bean,
但存入dependentBeanMap中的关系却是 B -> [A],这更像是一个假设,假设B如果依赖A的情况下会出现循环依赖。
随后在第二步的判断3中尝试判断这个假设是否成立,如果成立就代表出现循环依赖。
第二个例子:A depends-on B、B depends-on C、C depends-on A
1.当首次getBean(A)时,方法的入参为(A, B),发现dependentBeanMap里没有关于A的假设,所以执行判断2的返回语句(false),'假设B->[A]',随后调用getBean(B)。
2.当首次getBean(B)时,方法的入参为(B, C),在dependentBeanMap里发现关于B的假设 B->[A],判断3里确定当前假设不成立,然后进入下方的for循环逻辑。
B:
for ([A])
if (isDependent(A, C, [B])) 因为关于A的假设还没有提出,所以判断5会得到false。
for循环的逻辑结束,最终返回false,在方法外假设C->[B],随后调用getBean(C)。
3.当首次getBean(C)时,方法的入参为(C, A),在dependentBeanMap里发现关于C的假设 C->[B],判断3里确定当前假设不成立,然后进入下方的for循环逻辑。
C:
for ([B])
if (isDependent(B, C, [C]))
关于B的假设之前已经提出(B->[A]),但当前传入的第二个参数是C,代入判断3里发现假设不成立,随后用B的假设再次进入for循环的逻辑。
B:
for ([A])
if (isDependent(A, C, [C, B]))
因为关于A的假设还没有提出,所以判断5会得到false。
for循环的逻辑结束,最终返回false,在方法外假设A->[C],随后再次调用getBean(A)。
4.再次getBean(A)时,方法的入参为(A, B),在dependentBeanMap里发现关于A的假设 A->[C],判断3里确定当前假设不成立,然后进入下方的for循环逻辑。
A:
for ([C])
if (isDependent(C, B, [A]))
关于C的假设之前已经提出(C->[B]),当前传入的第二个参数是B,代入判断3里发现假设成立,返回true
for循环的逻辑结束,最终返回false,在方法外抛出循环依赖的异常。
在第二个例子中,值得注意的是什么?
- 现在有 A -> B -> C -> A 这样一个依赖链,从最前面的A开始执行isDependent(x, y),每次结束后都会提出一个假设 y -> x 放入到 dependentBeanMap 里。
- 判断3它做的工作就是验证这个假设是否成立,把关系图形化之后你会发现,
判断3的工作其实就是验证 当前bean 和 依赖链中上一个bean的依赖关系(例如:B和A的关系、C和B的关系),再说简单点就是相邻元素之间的依赖关系确认,能经得住判断3的验证代表相邻元素不存在循环依赖。
- 在这样一个图形化之后的关系中,你会发现似乎传入到方法里的第二个参数没有发挥作用,它发挥作用的地方是在最后for循环里,
而for循环的逻辑就有点特别了,假设当前bean是B,也就是说调用了isDependent(B, C),那for循环的逻辑就是把B之后一位的元素代入到位于B之前的所有元素的假设中进行假设判断,在当前调用链中就是让A与C确认关系。
一旦dependentBeanMap中存在了key为依赖链开头的的内容时,代表整个依赖链已经走过一遍了。
现在提出第三个例子:A depends-on B、 B depends-on C、 C depends-on D、 D depends-on A
可以得到这样一个依赖链: A -> B -> C -> D -> A。
在第二个例子中,已经掌握了循环依赖判断的基本逻辑,这里不再进行详细叙述,只是大概说明。
1.使用判断3进行相邻元素的以来确认,如果发现存在循环依赖关系直接抛出循环依赖的异常。
2.这里在第二个例子的基础上对for循环进行更详细的说明,之前说过它的逻辑是把y代入到位于x之前的所有元素的假设中进行假设判断。
以B举例,for循环的过程是这样的:isDependent(A, C, [B]) -> A还没有假设,返回false
以C举例,for循环的过程是这样的:isDependent(B, D, [C]) -> 将D带入B的假设(B->[A])中发现不成立 -> isDependent(A, D, [C, B]) -> A还没有假设,返回false
以D举例,for循环的过程是这样的:isDependent(C, A, [D]) -> 将A带入C的假设(C->[B])中发现不成立 -> isDependent(B, A, [D, C]) -> 将A带入B的假设(B->[A])中发现成立,返回true。
只要for循环的逻辑中存在任意一个使假设成立的项,那就是存在循环依赖。
如果你到这里还是不太懂for循环的逻辑,可以这么理解。
现在A、B、C、D已经系在一根直绳上了,每个元素都只知道它之前一位的是什么。那如何确定D和A相连?
只需要从D开始向前找(D->A),看A有没有出现在过这个链上,如果出现过就代表出现循环依赖。
这就是isDependent方法的逻辑,如果干看看不明白就画一下线,画一下就明白了。
// DefaultSingletonBeanRegistry
protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}
// DefaultSingletonBeanRegistry
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
if (alreadySeen != null && alreadySeen.contains(beanName)) { // 判断1
return false;
}
String canonicalName = canonicalName(beanName);
// 注意`registerDependentBean(dep, beanName)`
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) { // 判断2
return false;
}
// 将y带入假设看是否成立,成立就代表存在循环依赖
if (dependentBeans.contains(dependentBeanName)) { // 判断3
return true;
}
for (String transitiveDependency : dependentBeans) { // 判断4
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) { // 判断5
return true;
}
}
return false;
}
2. 补充-简述bean的创建过程
这里简单做个记录,简单描述一个创建步骤。
1.处理depends-on
2.创建bean
2.1 准备MethodOverrides
2.2 调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation (非合成才行)
2.3 通过各种方式实例化bean(例如:构造函数、自定义lambda、工厂等方式)
2.4 调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
2.5 调用InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation (非合成才行)
2.6 调用InstantiationAwareBeanPostProcessor#postProcessProperties
2.7 调用InstantiationAwareBeanPostProcessor#postProcessPropertiesValues
2.8 填充bean属性
2.9 调用Aware相关方法
2.10 调用BeanPostProcessor#postProcessorBeforeInitialization (非合成才行)
2.11 调用init方法
2.12 调用BeanPostProcessor#postProcessorAfterInitialization (非合成才行)
2.13 尝试注册为DisposableBean
3. 类型转换
InstantiationAwareBeanPostProcessor
在bean实例化前后
和对参数
发挥了作用。
BeanPostProcessor
在bean初始化前后
发挥了作用。
3. 补充-循环依赖
Spring中有多种循环依赖情况的出现,每种循环依赖的处理方式都有所不同,这里举例几种。
3.1. depends-on导致的循环依赖
3.1.1. 触发方式
class A {
// empty
}
class B {
// empty
}
<bean id="a" class="a.b.c.A" depends-on="b"/>
<bean id="b" class="a.b.c.B" depends-on="a"/>
3.1.2. 会抛出的异常
Circular depends-on relationship between 'A' and 'B'
3.1.3. 解决方式
1.手动去掉标签内的depends-on
属性或者类中@DependsOn
注解。
2.自己实现一个ApplicationContext
,在postProcessBeanFactory
方法中使用BeanDefinition#setDependsOn(?)
遍历修改。
源码抛出异常的位置以及检测逻辑
相关的检测逻辑位于AbstractBeanFactory#doGetBean(String, Class<T>, Object[], boolean)
方法中对isDependent
方法的调用处。
它的检测逻辑在上文关于isDependent
方法的分析下有详细描述。
它主要依靠dependentBeanMap
这个Map数据结构来实现的检测。
3.2. 属性注入阶段导致的循环依赖
3.2.1. 触发方式(方式一)
// @Autowired、@Resource注解、property属性产生的循环依赖
@Service
class A {
@Autowired
B b;
}
@Service
class B {
@Autowired
A a;
}
@Test
public void test() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml"}, false, null);
// 必须设置为false才行
ac.setAllowCircularReferences(false);
ac.refresh();
}
3.2.2. 触发方式(方式二)
// 使用构造函数实例化bean时受限于属性的循环依赖
@Service
class A {
@Autowired
public A(B b) {}
}
@Service
class B {
@Autowired
public B(A b) {}
}
3.2.3. 会抛出的异常
Requested bean is currently in creation: Is there an unresolvable circular reference?
3.2.4. 解决方式
对于方式一来说,如果不手动设置
setAllowCircularReferences(false)
,是无法复现出属性注入导致的循环依赖的。
也就是说默认情况下这个值为true,如果属性出现循环依赖,Spring不会抛出任何异常,所以默认情况下压根不需要处理。
对于方式二来说,可以在其中一个构造函数的属性上添加
@Lazy
注解,同时在构造函数内也不能使用这个参数。
3.2.5. 源码抛出异常的位置以及检测逻辑
相关的检测逻辑位于DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory)
方法中对beforeSingletonCreation
方法的调用处。
本例中一共列举了4种触发方式,它们都是属性注入阶段导致的循环依赖,但他们的检测逻辑不是同一部分控制的。
1.
CommonAnnotationBeanPostProcessor
负责对@Resource
修饰的内容进行值的注入。
2.AutowiredAnnotationBeanPostProcessor
负责对@Autowired
修饰的内容进行值的注入。
3.ConstructorResolver#autowireConstructor
负责对使用构造函数进行实例化的bean进行处理。
4.AbstractAutowireCapableBeanFactory#applyPropertyValues
负责对property属性
的转换与注入。
上面展示了一部分关于property属性处理的源码,那这里以property属性
的循环依赖检测为例进行说明,其他的自己看吧。
它主要依靠earlySingletonObjects
、singletonFactories
、singletonsCurrentlyInCreation
这些数据结构来实现的检测。
举例: A类中引用B,B类中引用A
事先说明,这是对下面的格式化描述的解释
前:
1.xxxxx
后:
这其中的前和后都是针对 1.xxxxx 的,注意理解
具体分析步骤:
前: singletonsCurrentlyInCreation: 添加A
1.对A进行实例化
后: singletonFactories: 添加A
2.对A进行属性填充
3.解析到B的引用,调用getBean(B)
前: singletonsCurrentlyInCreation: 添加B
4.对B进行实例化
后: singletonFactories: 添加B
5.对B进行属性填充
6.解析到A的引用,调用getBean(A)
后:
earlySingletonObjects: 添加A (singletonsCurrentlyInCreation中存在A 并且 singletonFactories中存在A)
singletonFactories: 移除A
在getSingleton(A)方法中,在从singletonFactories中删除A之前获取到它的值作为返回值。
7.完成B的一切工作
后:
singletonsCurrentlyInCreation: 删除B
singletonObjects: 添加B
earlySingletonObjects: 删除B (压根就没添加过B)
singletonFactories: 删除B
8.完成A的一切工作
后:
singletonsCurrentlyInCreation: 删除A
singletonObjects: 添加A
earlySingletonObjects: 删除A
singletonFactories: 删除A (之前就删了)
如果按照网络上其他文章一样描述的话,可以自己替换一下
把singletonObjects看作一级缓存
把earlySingletonObjects看作二级缓存
把singletonFactories看作三级缓存
例子中可以看出来,如果依赖链长的话,逻辑其实没什么区别,主要是嵌套层次会加深而已,所以这里不进行长依赖链的分析了。
上面的分析是在默认情况下进行的(代表允许属性之间的循环依赖),一切运行正常。
那么产生了一个问题,当设置了setAllowCircularReferences(false)
时,到底是哪里了发挥作用使得程序抛出循环依赖的异常?
可以结合上面的步骤看一下`AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[])`方法中`earlySingletonExposure`属性的是怎么来的。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
很明显这第二个参数'allowCircularReferences'发挥了重要作用,它作为了起点,促使整个程序走向循环依赖异常,可以根据上面的步骤和源码进行一下分析。
首先,当'allowCircularReferences'为'false'时,Spring不会向'singletonFactories'中设置值A。
然后,很明显在上面的第6步里,因为'singletonFactories'中不存在A,所以A不会存在晋升行为,而且它也使得返回值为null。
因为返回值为null,所以Spring认为这个A还没创建,所以又跑去创建A,跟踪源码直到'DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory)'里,可以看到`beforeSingletonCreation(beanName)`这么一行代码,
它里面对'!singletonsCurrentlyInCreation.add(A)'的操作会使得程序直接抛出循环依赖的异常。
补充:
singletonsCurrentlyInCreation 实际上操作的是Map,当对Map调用add(X)时,如果Map中之前就存在X,那么最终会返回false。
对
singletonObjects
、earlySingletonObjects
、singletonFactories
属性的说明。
在上面的例子中,可以很明显的看出来,singletonObjects
、earlySingletonObjects
、singletonFactories
这3个东西是干什么的。
singletonObjects[Map]
最简单,它里面存放的是创建完成的bean,它的赋值在当前bean创建完成后进行。
earlySingletonObjects[Map]
比其它两个稍微复杂一点点,它里面存放的像是当前已被发现在循环依赖链中的bean(一时没想到合适的描述),稍后具体举例说明。
singletonFactories[Map]
也挺简单的,它像个是否允许循环依赖功能的开关,用于辅助earlySingletonObjects
的逻辑执行。
还有一个要注意的就是singletonsCurrentlyInCreation
,它才是最后抛出属性循环依赖异常的守门员。
下面使对这些属性的额外补充。
对'earlySingletonObjects'这个东西的存入时机进行细致说明。
假设1: A 中属性依赖 B,B 中属性依赖 A
把这个关系变成链状展示(简化描述): A -> B -> A 开头的A和结尾的A是同一个
默认情况下:
第一次处理A时,Spring会在'singletonsCurrentlyInCreation'和'singletonFactories'中标记A,之后发现它的属性依赖于B,会对B展开第一次处理。
第一次处理B时,Spring会在'singletonsCurrentlyInCreation'和'singletonFactories'中标记B,之后发现它的属性依赖于B,会再次对A展开处理,但Spring现在还不知道它们之间有没有循环依赖。
第二次处理A时,Spring发现'singletonsCurrentlyInCreation'中已经存在A了,也就知道'singletonsCurrentlyInCreation'集合中的项之间存在循环依赖。
到这里,实际上又回到了依赖链的开头,已经是第二次处理A了,所以'singletonFactories'内存储的A会晋升到'earlySingletonObjects'里面,来表示A出现在了循环依赖中。
而'singletonFactories'更像是个循环依赖的开关,是辅助'earlySingletonObjects'来完成逻辑处理的,一旦不允许循环依赖(使singletonFactories不工作),那么程序检查到循环依赖就会抛出异常。
假设2: A 中属性依赖 B,B 中属性依赖 C,C 中的属性依赖于 A和B
把这个关系变成链状展示(简化描述): A -> B -> C -> A, B 开头的A和结尾的A是同一个
默认情况下:
第一次处理A时,Spring会在'singletonsCurrentlyInCreation'和'singletonFactories'中标记A,之后发现它的属性依赖于B,会对B展开第一次处理。
第一次处理B时,Spring会在'singletonsCurrentlyInCreation'和'singletonFactories'中标记B,之后发现它的属性依赖于C,会对C展开第一次处理。
第一次处理C时,Spring会在'singletonsCurrentlyInCreation'和'singletonFactories'中标记C,之后发现它的属性依赖于A, B,会分别再次对A和B展开处理,但Spring现在还不知道它们之间有没有循环依赖。
第二次处理A时,Spring发现'singletonsCurrentlyInCreation'中已经存在A了,把A会晋升到'earlySingletonObjects'里面。
第二次处理B时,Spring发现'singletonsCurrentlyInCreation'中已经存在B了,把B会晋升到'earlySingletonObjects'里面。
最后这里补充一下这点:
earlySingletonObjects
和singletonFactories
只有一者里面可以存在当前bean。
earlySingletonObjects
和singletonFactories
只针对当前创建的bean(包括它的依赖链)有用。网上还有一个这样的问题:为什么解决循环依赖使用了三级缓存?
这个问题实际上是关于属性的循环依赖的,两者都有存在的必要,在下面4.3小结有说明。
三级缓存中存放的是一个beanName到lambda函数的映射,用于
这是一些可能自己调试源码时方便理解的笔记,没啥大用,不想看就跳过。
关于property属性的循环依赖有这么几个需要关注的点:
1.`AbstractBeanFactory#doGetBean(String, Class<T>, Object[], boolean)`
第三行`getSingleton(beanName)`
2.`DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory)`
beforeSingletonCreation(beanName) -> (发生在bean实例化之前),把当前bean放到singletonsCurrentlyInCreation中
afterSingletonCreation(beanName) -> (发生在bean创建完成之后),把当前bean从singletonsCurrentlyInCreation里移除
addSingleton(beanName, singletonObject) -> (发生在bean创建完成之后),把当前bean放到singletonObject中 并且 从singletonFactories和earlySingletonObjects中移除当前bean
3.AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[])
两处对`earlySingletonExposure`属性的判断
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); -> (发生在bean实例化之后,初始化之前),把当前bean放到singletonFactories中
getSingleton(beanName, false) -> (发生在bean创建完成之后),尝试从singletonObject和earlySingletonObjects中取值,实际上也拿不到值。
singletonObjects
存 -> bean的相关所有工作都完成了之后(FactoryBean除外,它需要额外操作)。 见`DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory)`的`addSingleton(beanName, singletonObject)`
删 -> 在销毁单例时(很难发生,不考虑它的删除情况)
代表含义 -> 是一个完整可用的bean实例
earlySingletonObjects
存 -> 调用getSingleton(beanName, true)时,当前bean存在于singletonFactories中
删 -> 1.bean的相关所有工作都完成了之后 2.singletonFactories存数据时
singletonFactories
存 -> 在bean实例化之后,初始化之前
删 -> 1.bean的相关所有工作都完成了之后 2.调用getSingleton(beanName, true)时,当前bean存在于singletonFactories中
4. 补充-动态代理
在bean的创建过程中,有这么几个地方会导致代理的出现,当然,前提是你配置了相关的内容,没配置的话就不会有动态代理的出现。
关于
Advice
、Advisor
、Pointcut
的说明
Advice
:定义的是围绕目标的一组增强行为(要织入的代码)。
PointCut
:定义的是切面要织入的位置。
Advisor
:负责将Advice
和PointCut
进行联系,指出切面应该织入的位置。
4.1. 通过BeanPostProcessors来创建bean时生成代理类
这一步是在试图使用常规方式进行实例化bean之前进行的
在AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
里有这么一行代码调用resolveBeforeInstantiation
,它实际上是对InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
的调用。
这里唯一需要关注的是
AbstractAutoProxyCreator
实现,以及它的子类AspectJAwareAdvisorAutoProxyCreator
,这个类是在BeanDefinition
解析aop的命名空间时注册的,在项目启动时可以观察bean注册日志找名为internalAutoProxyCreator
的bean。
// AbstractAutoProxyCreator
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
// 1. beanName为空
// 2. targetSourcedBeans 不包含当前beanName (类私有的,在最初是没有值的)
// 只要满足其中一点就可以进入 if 代码块,默认情况下都会进入
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 判断缓存里面是否有内容,不用想最初是没有的。
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 1.是否是基础实现类
// 只要bean class派生自 Advice、Pointcut、Advisor、AopInfrastructureBean 其中任意一种, 就会返回true
// 如果返回true,就表示当前的类是不应该被代理的。
// 2.是否应该跳过当前类
// 如果给定的bean不应该考虑由这个后处理器自动代理,子类应该重写这个方法以返回true,返回true表示应该跳过当前类。
// 默认情况下会对.ORIGINAL结尾的类进行跳过。
// 只要有一者为true,就会进入 if 代码块。
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 对于我们常规情况下自定义的bean,上面的判断是拦不住的,也就是说会执行下面的代码,但TargetSource默认情况下没有值,所以默认情况下整个方法实际上什么也没执行。
// 这里提供了一种让使用者自定义创建代理的实现,默认是没有TargetSource实现的。
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 获取到类可以使用的Advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 创建代理类,这里暂时不分析
// 4个参数分别是,bean的类,bean的名称,适用的Advisor集合、要代理的目标
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
关于
TargetSource
,文档上描述的很详细
Spring Core 文档 - 使用TargetSource实现
4.2. lookup-method或replaced-method的使用导致生成代理类
在
AbstractAutowireCapableBeanFactory#createBean
方法里,默认情况下会使用最下方的instantiateBean(beanName, mbd)
来尝试实例化bean,而且使用的是bean class的默认构造函数,但是一旦使用了
lookup-method
或replaced-method
就会导致CGLIB代理类的创建。
见CglibSubclassingInstantiationStrategy#instantiate(Constructor, Object[])
。
4.3. 填充参数时生成代理类
在之前的
关于property属性对引用的赋值
小结内,已经展示过bean的引用类型的属性
会使用getBean(refName)来从获取容器中获取实例对象,然后注入到目标bean中。
这里要配合如下两处代码一起理解整个过程。
AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition, Object[]) 中的代码片段
(发生在bean实例化后,初始化前)
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// getEarlyBeanReference方法内部的逻辑涉及到了代理类的创建,很值得注意。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
AbstractBeanFactory#doGetBean(String, Class<T>, Object[], boolean) 中的代码片段
(在填充参数时会调用到)
Object sharedInstance = getSingleton(beanName);
在展示属性注入导致的循环依赖小结就说过'getSingleton(beanName)'的逻辑,'singletonFactories'和'earlySingletonObjects'这两个数据结构的数据来源与晋升逻辑都已经做过叙述。
在其中getSingleton(beanName)方法的调用链中会执行到这么一行代码
singletonObject = singletonFactory.getObject();
它调用的内容就是对之前添加的内容的调用
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
同时也会把执行结果晋升到'earlySingletonObjects'里,所以只需要搞明白getEarlyBeanReference方法的含义就行。
// AbstractAutowireCapableBeanFactory
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 这里也是关注AbstractAutoProxyCreator类的实现
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
// AbstractAutoProxyCreator
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
this.earlyProxyReferences.add(cacheKey);
}
return wrapIfNecessary(bean, beanName, cacheKey);
}
// AbstractAutoProxyCreator
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 主要还是看下面的代码,这下面的代码核心区域和4.1小结相似
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理类
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
4.4. 对createProxy方法的说明
无论是4.1小结还是4.3小结,里面都有对
createProxy
方法的调用,这里额外写一个小结分析这个方法内的代码。
// AbstractAutoProxyCreator
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory(); // 创建 ProxyFactory 实例
proxyFactory.copyFrom(this);
// 是否直接代理目标类以及任何接口,如果为true就是直接代理
if (!proxyFactory.isProxyTargetClass()) { // 默认为false
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 会把目标类中满足下面三个条件的父接口记录下来,添加给ProxyFactory的interfaces属性,之后会用到
// 1.没有配置回调方法的(例如:InitializingBean、DisposableBean、Closeable等)
// 2.不是内部语言的(例如:类名不等于GroovyObject、类名不以.cglib.proxy.Factory结尾、类名不以.bytebuddy.MockAccess结尾)
// 3.接口内方法数量大于0
// 如果没有满足条件的接口,则会执行setProxyTargetClass(true)
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource); // 设置要代理的类
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader()); // 创建代理
}
// ProxyFactory
public Object getProxy(@Nullable ClassLoader classLoader) {
// createAopProxy() 方法用于确认使用哪种 AopProxy 来创建代理
// 实际上就只提供了2中,一种是JDK形式的;另一种是CGLIB形式的
// getProxy(classLoader) 方法很简单,只是看起来麻烦,主要就是生成代理类并返回实例对象。
return createAopProxy().getProxy(classLoader);
}
// getProxy方法的调用链
// ProxyCreatorSupport#createAopProxy()
// DefaultAopProxyFactory#createAopProxy(AdvisedSupport)
// DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 1. 使用优化的代理策略 (默认为false)
// 2. 目标类本身被代理而不是目标类的接口 (也就是说当前类没有ProxyInterface)
// 3. 不存在用户自定义的ProxyInterface (上面有说是什么)
// 满足其中一个,就会进入if代码块 (举个最简单的例子,如果目标类没有接口,则会进入if代码块,而且会使用CGLIB来进行代理)
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//
return new ObjenesisCglibAopProxy(config);
}
else {
// 开发中编写的Service实现类会执行这里。
return new JdkDynamicAopProxy(config);
}
}
更多关于代理模式的描述和示例 -> 跳转地址
JDK Dynamic Proxy: 只能对接口进行代理
CGLIB: 不受必须实现接口的限制,但对于final方法无法代理