Spring Ioc中Bean的加载实现方法

发布时间:2021-06-24 09:22:45 作者:chen
来源:亿速云 阅读:149

这篇文章主要讲解了“Spring  Ioc中Bean的加载实现方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring  Ioc中Bean的加载实现方法”吧!


createBean()

代码:

//AbstractAutowireCapableBeanFactory.java

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

	if (logger.isDebugEnabled()) {
		logger.debug("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;

	// Make sure bean class is actually resolved at this point, and
	// clone the bean definition in case of a dynamically resolved Class
	// which cannot be stored in the shared merged bean definition.
	//判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// Prepare method overrides.
	//校验和准备Bean中的方法覆盖
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		//如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
		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);
	}

	try {
		//创建Bean的入口
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	catch (BeanCreationException ex) {
		// A previously detected exception with proper bean creation context already...
		throw ex;
	}
	catch (ImplicitlyAppearedSingletonException ex) {
		// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
		throw ex;
	}
	catch (Throwable ex) {
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
	}

这段代码分为以下几个步骤:

  1. 判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载

  2. 校验和准备Bean中的方法注入

  3. 如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象

  4. 创建Bean

第1步

主要是获取bean的class,并设置到BeanDefinition中

第2步

主要是处理方法注入
代码:

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
	// Check that lookup methods exists.
	//检测是否存在方法注入,并循环预处理方法注入
	if (hasMethodOverrides()) {
		Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
		synchronized (overrides) {
		        //遍历处理
			for (MethodOverride mo : overrides) {
				prepareMethodOverride(mo);
			}
		}
	}
	}

prepareMethodOverride(mo):

protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        // 统计注入的方法个数   
	int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
	if (count == 0) {
		throw new BeanDefinitionValidationException(
				"Invalid method override: no method with name '" + mo.getMethodName() +
				"' on class [" + getBeanClassName() + "]");
	}
        // 如果为1,则将注入方法标记为未重载
	// 注意:当有多个重载方法时,为了确定调用哪个具体的方法,Spring对重载方法的参数解析是很复杂的
	// 所以,如果注入方法没有被重载这里就将其标记,省去了对方法参数的解析过程,直接调用即可
	else if (count == 1) {
		// Mark override as not overloaded, to avoid the overhead of arg type checking.
		mo.setOverloaded(false);
	}
	}

代码读到这里,大家可能有疑问,从代码上看明明是处理的方法重载,但是为什么处理的是方法注入呢?而且如果我们在bean里设置几个方法重载的话,hasMethodOverrides()方法返回的是false。如果我们打开 AbstractBeanDefinition 类的 hasMethodOverrides() 方法,就能打消我们之前的疑问。

public boolean hasMethodOverrides() {
		return (this.methodOverrides != null && !this.methodOverrides.isEmpty());
	}

其中methodOverrides是做什么的呢?通过类名AbstractBeanDefinition我们可以发现,该类是BeanDefinition的一个子类,那么它保存的应该是我们解析到的beanDefinition,spring在解析配置文件的时候,如果发现配置了replace-method或者lookup-method那么,就会对应的标签解析,并存入到 AbstractBeanDefinition 的 methodOverrides 属性中,那么当bean实例化的时候,如果检测到了methodOverrides属性不为空,则动态的为当前bean生成代理并使用相应的拦截器对bean做处理,这里大家只要把概念搞清楚即可。

第3步

主要是对bean前置后置处理器的处理,给 BeanPostProcessors 后置处理器一个返回代理对象的机会
详细代码:

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
	Object bean = null;
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// Make sure bean class is actually resolved at this point.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) {
				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				if (bean != null) {
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
	}

如果代理对象不为空,则直接返回代理对象,这一步骤有非常重要的作用,Spring 后续实现 AOP 就是基于这个地方判断的。
这个方法核心就在于 applyBeanPostProcessorsBeforeInstantiation()applyBeanPostProcessorsAfterInitialization() 两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。

第4步

doCreateBean()
创建Bean

//真正创建Bean的方法
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
		throws BeanCreationException {

	// Instantiate the bean.
	//BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
	        //单例模式,删除factoryBean缓存
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
	        //使用合适的实例化策略来创建Bean:工厂方法、构造函数自动注入、简单初始化
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	//从包装类中获取实例化的Bean
	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 {
			        //调用PostProcessor后置处理器,修改 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.
	// 解决单例模式的循环依赖
	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));
	}

	// Initialize the bean instance.
	//Bean对象的初始化,依赖注入在此触发
	//这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
	Object exposedObject = bean;
	try {
		//将Bean实例对象封装,并且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) {
		//获取指定名称的已注册的单例模式Bean对象
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			//根据名称获取的已注册的Bean和正在实例化的Bean是同一个
			if (exposedObject == bean) {
				//当前实例化的Bean初始化完成
				exposedObject = earlySingletonReference;
			}
			//当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				//获取当前Bean所依赖的其他Bean
				for (String dependentBean : dependentBeans) {
					//对依赖Bean进行类型检查
					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.
	//注册完成依赖注入的Bean
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
	}

代码很长,不过别慌,我们来按步骤分析一波

  1. 如果是单例模式,从factoryBeanInstanceCache 缓存中获取BeanWrapper 实例对象并删除缓存

  2. 调用 createBeanInstance() 实例化 bean
    (主要是将 BeanDefinition 转换为 BeanWrapper)

  3. 后置处理

  4. 单例模式的循环依赖处理

  5. 初始化 bean 实例对象
    (属性填充)

  6. 依赖检查

  7. 注册 DisposableBean

doCreateBean() 完成 bean 的创建和初始化工作,内容太多,比较复杂,这里只列出大致流程,接下来我们将分几篇文章来分别阐述相关内容。

感谢各位的阅读,以上就是“Spring  Ioc中Bean的加载实现方法”的内容了,经过本文的学习后,相信大家对Spring  Ioc中Bean的加载实现方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. 一文解析Spring IOC面试中常问的那些核心题!
  2. Spring的概念详解

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

spring bean

上一篇:python如何使用递归回溯完美解决八皇后的问题

下一篇:Pytorch中.pth权重文件的示例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》