Spring源码解析二十五(bean的实例化)

上一篇,我们了解了Spring 默认是如何实例化bean的,在实例化bean之前,Spring 还是做了很多的准备工作。我们最后找的了Spring 实例化bean的核心位置也就是doCreateBean。我们今天接着doCreateBean方法开始分析Spring是如何实例化bean的。

我们到doCreateBean 方法中看下:

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			// 创建bean实例的包装类BeanWrapper
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		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 {
					// 提供了一个通过后处理BeanPostProcessor,修改合并后的BeanDefinition的机会
					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.
		// 如果当前实例的bean为单例,并且允许循环引用,并且当前的单例bean正在处于创建中,此时允许暴露早期单例bean
		// 这个也是之前可以在对象工厂缓存中,获取到ObjectFactory的关键,ObjectFactory 就是在这里添加的
		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");
			}
			// 添加早期实例化bean的ObjectFactory到单例工厂缓存中
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// 为bean设置各种属性
			populateBean(beanName, mbd, instanceWrapper);
			// 初始化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);
			}
		}

		if (earlySingletonExposure) {
			// 从二级缓存earlySingletonReference中,获取早期单例bean
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				// 判断是否有其他的bean依赖当前实例化的bean
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							// 将那些依赖当前实例化的bean的名称,添加到集合actualDependentBeans中
							actualDependentBeans.add(dependentBean);
						}
					}
					// 如果发现集合actualDependentBeans不为空,就抛出异常
					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 " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			// 为bean注册DisposableBean
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

这个doCreateBean代码还是很多的,我们会慢慢的把这些方法中的一些关键点进行分析。
在这里插入图片描述
首先,如果发现BeanDefinition为单例类型,就会从factoryBeanInstanceCache中获取一个BeanWrapper,默认BeanDefinition的类型就是单例的,并且这个factoryBeanInstanceCahce是为空的,所以,我们获取到的instanceWrapper最终也是空的。这个factoryBeanInstanceCache就是一个缓存,是用来存放FactoryBean实例对应的BeanWrapper,而BeanWrapper我们可以理解为就是bean实例的一个包装类而已,在得到bean的最终实例之前,bean的实例还得依附BeanWrapper。接下来可以看到,如果缓存factoryBeanInstanceCache中获取不到instanceWrapper之后,Spring 就会调用createBeanInstance方法来创建一个BeanWrapper。

我们到createBeanInstance里面看下:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		// 再次解析BeanDefinition 中的class,确保现在bean的class 已经解析好了
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		// 如果bean的类不是public修饰的,并且没有通过反射设置允许访问的权限 此时就不能通过反射创建bean了,此时就会提取抛出异常
		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());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}
		// 如果属性factory-method 不为空,则通过配置好的工厂方法来实例化bean
		if (mbd.getFactoryMethodName() != null) {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		// 实例化bean时,如果参数为空
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

		// Candidate constructors for autowiring?
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// Preferred constructors for default construction?
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		return instantiateBean(beanName, mbd);
	}

在这里插入图片描述
首先会调用方法resolveBeanClass,从BeanDefinition mbd中解析获取Class,我们已经调用过一次方法resolveBeanClass,并且成功获取过一次bean的class了,而spring之所以在这里重复调用一次该方法,只不过是想要确认bean的Class一定是能解析成功的。接下来,Spring会判断bean对应的Class如果不是被public关键词修饰的,并且也没有通过反射机制来设置这个Class是可以访问的,就会抛出异常。

我们继续往后看:
在这里插入图片描述
上图中,会通方法getFactoryMethodName,判断下bean对应的BeanDefinition中,是否存在属性factoryMethodName的值,那这个属性factoryMethodName是做什么的呢?
我们通过一个案例说明:
在这里插入图片描述
在这里插入图片描述
我们创建了User5类和UserFactory 类。UserFactory 类中就只有一个方法getUser,而getUser方法中就是通过new关键字创建了一个User5类型的对象,来自定义bean的实例化逻辑。需要注意的是,这里getUser方法为static关键字修饰的静态方法,现在我们可以认为UserFactory 就是专门生产User5实例的一个静态工厂。

最后,我们把UserFactory类配置到xml中:
在这里插入图片描述
在bean标签中,通过class属性配置好了UserFactory类,而且,我们还特意配置了属性factory-method的值,属性factory-method指定的静态工厂方法就是getUser。这样的话,当我们从Spring容器中获取名称为user5的bean时,Spring就会调用UserFactory类中的getUser方法,来实例化一个User5类型的bean了。
我们执行代码:
在这里插入图片描述
执行结果:
在这里插入图片描述
Spring既然可以通过静态工厂方法来实例化bean,那能不能通过实例工厂方法来实例化bean呢?也就是通过不带static关键修饰的工厂方法?答案当然也是可以的,我们只需要简单修改下代码以及相应的xml配置:
在这里插入图片描述
我们将UserFactory中,getUser方法前面的static关键字去掉。在修改下applicationContext.xml中的配置:
在这里插入图片描述
可以看到,我们将UserFactory类单独配置在一个bean标签中,然后通过另外一个bean标签中的factory-method属性引用了UserFactory这个bean,但是,关键的factory-method属性是必须要配置的,表示指定哪个工厂方法来实例化bean。
当我们从Spring中获取名称为user5的bean时,Spring首先会找到factory-bean属性指定的bean,先实例化这个bean,然后调用factory-bean对应的bean的getUser方法,得到最终实例化好的bean。

我们回到刚才的代码:
在这里插入图片描述
在上图中,getFactoryMethodName方法获取的就是bean标签中factory-method属性配置的工厂方法名称,如果getFactoryMethodName方法的返回值不为null,Spring就会按照我们刚才案例中看到的那样,调用工厂方法来实例化bean了,就不会走Spring的默认实例化bean的逻辑了,可以看到这里同样也是我们可以利用的一个扩展点。在方法instantiateUsingFactoryMethod中的逻辑,大家了解下就可以了,因为方法instantiateUsingFactoryMethod中的代码逻辑,本质上就是一些反射相关的操作,核心就是像我们刚才分析的一样,就是判断一下当前是通过静态工厂方法,还是通过实例工厂方法来实例化bean的实例。

接下来,我们继续往后看:
在这里插入图片描述
初次实例化bean时,BeanDefinition中的resolvedConstructorOrFactoryMethod属性默认是为空的,所以不会走到这部分的代码。我们接着往下看:
在这里插入图片描述这块没什么特别重要的逻辑,就是通过determineConstructorsFromBeanPostProcessors方法,执行一些后处理器BeanPostProcessor中的逻辑,而这些后处理器中的逻辑,主要是获取Class中的多个重载构造方法ctors。在if分支中,其中有一个判断逻辑为 mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR,虽然我们不太清楚AUTOWIRE_CONSTRUCTOR是什么,但是通过AUTOWIRE_CONSTRUCTOR的名称,我们大概就可以知道和@Autowired注解有关系。而且,在我们当前要实例化的bean中,确实也没有其他重载的构造方法,所以,接下来代码就会来到最后一个方法instantiateBean中。我们到方法instantiateBean中看下:
在这里插入图片描述
首先会通过方法instantiate实例化一个实例beanInstance,然后将bean的实例封装到BeanWrapperImpl中。这个BeanWrapperImpl就是简单包装了一下bean的实例而已。这个bean的实例时如何创建的呢?我们到方法instantiate看下:
在这里插入图片描述
在这里插入图片描述
首先会判断当前bean标签中是否配置了属性lookup-method或者replace-method。如果配置了这两个属性就意味着实例化bean的时候需要覆写bean中的方法,具体如何覆写呢?
可以看到,Spring默认会调用方法instantiateWithMethodInjection,我们可以到方法instantiateWithMethodInjection里面看下:在这里插入图片描述
在这里插入图片描述
接下来会到CglibSubclassingInstantiationStrategy类中,我们再到CglibSubclassCreator中的方法instantiate看下:

在这里插入图片描述
方法最后是对looku-method和replace-method指定需要覆盖的方法,添加了方法拦截器LookupOverrideMethodInterceptor和ReplaceOverrideMethodInterceptor 进行增强处理,也就是达到一个覆盖写方法的效果。

我们在到createEnhancedSubclass方法中看下:
在这里插入图片描述
从这里可以看到,Spring底层对于需要覆写的方法的那些bean的实例化,其实就是通过cglib动态代理来做的。
我们现在回到我们的主流程上面,因为我们的bean是没有覆写方法所以会走到下面的这个分支:
在这里插入图片描述
我们到方法BeanUtils.instantiateClass方法里面看下:
在这里插入图片描述
可以看到Spring默认就是通过jdk反射来实例化bean的。

我们总结一下今天的流程:
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SpringBean生命周期源码主要涉及到Bean的初始化、依赖注入、后置处理、销毁等各个阶段。以下是一个简化的Spring Bean生命周期源码解析: 1. 实例化(Instantiation):Spring通过反射机制实例化Bean对象。这是通过调用构造函数或者工厂方法来完成的。 2. 属性注入(Property Injection):在实例化后,Spring将通过依赖注入(Dependency Injection)来设置Bean的属性值。这是通过调用setter方法或者直接访问字段来完成的。 3. Aware接口回调:Spring会检查Bean是否实现了某些Aware接口(如BeanNameAware、ApplicationContextAware等),并通过回调方法将相关的信息注入到Bean中。 4. BeanPostProcessor前置处理(BeanPostProcessor Pre-Initialization):Spring会检查是否有注册的BeanPostProcessor,如果有,则在Bean初始化前调用它们的postProcessBeforeInitialization方法。 5. 初始化(Initialization):初始化阶段包括两个步骤: a. 调用自定义的初始化方法(如通过@PostConstruct注解标记的方法或实现了InitializingBean接口的afterPropertiesSet方法)。 b. 调用BeanPostProcessor后置处理方法postProcessAfterInitialization。 6. 使用(In Use):此时Bean已经初始化完成,可以使用了。 7. 销毁(Destruction):在容器关闭或者手动销毁时,Spring会调用销毁方法来释放Bean占用的资源。 a. 调用自定义的销毁方法(如通过@PreDestroy注解标记的方法或实现了DisposableBean接口的destroy方法)。 b. 调用BeanPostProcessor后置处理方法postProcessBeforeDestruction。 以上是简化的Spring Bean生命周期源码解析,实际的源码会更加复杂和详细。Spring通过BeanPostProcessor和各种回调接口,提供了丰富的扩展点和生命周期管理功能,使开发者能够在Bean的不同阶段进行自定义操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

youngerone123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值