Spring源码(六)-创建Bean流程-createBean

1,468 阅读6分钟

createBean 方法总体可以分为四个小方法:

  • resolveBeanClass:加载 Class 对象
  • prepareMethodOverrides:对通过 XML 定义的 bean 中的lookup-methodreplace-method属性进行预处理
  • resolveBeforeInstantiation:实例化前应用后处理器
  • doCreateBean:创建 Bean

接下来就一个一个来看吧!

resolveBeanClass

首先调试进入AbstractAutowireCapableBeanFactory类的createBean

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

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

		// 使用类加载器根据 class 或者根据 className 来加载 Class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
      //省略代码...
}

进入AbstractBeanFactory类中的resolveBeanClass方法,注意typesToMatch的类型可能为FactoryBean.classtypesToMatch是一个可变参数。自己再DeBug的时候可以找找resolveBeanClass方法在哪些地方被调用。

@Nullable
	protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
			throws CannotLoadBeanClassException {
		//BeanDefintion是在扫描的时候创建的,
		//但是AbstractBeanDefinition中存在一个beanClass属性
		try {
			// 如果beanClass是Class,就直接返回beanClass
			if (mbd.hasBeanClass()) {
				return mbd.getBeanClass();
			}
            //忽略
			if (System.getSecurityManager() != null) {
				return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
					doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
			}
			else {
				// 加载AbstractBeanDefinition中beanClass中所指定的类名对应的类
				return doResolveBeanClass(mbd, typesToMatch);
			}
		}
		catch (PrivilegedActionException pae) {
			ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
			throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
		}
		catch (ClassNotFoundException ex) {
			throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
		}
		catch (LinkageError err) {
			throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
		}
	}

进入 AbstractBeanFactory类中的doResolveBeanClass方法

@Nullable
	private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
			throws ClassNotFoundException {
		// 拿到类加载器
		ClassLoader beanClassLoader = getBeanClassLoader();
		ClassLoader dynamicLoader = beanClassLoader;
		boolean freshResolve = false;

		if (!ObjectUtils.isEmpty(typesToMatch)) {
			ClassLoader tempClassLoader = getTempClassLoader();
			if (tempClassLoader != null) {
				dynamicLoader = tempClassLoader;
				freshResolve = true;
				if (tempClassLoader instanceof DecoratingClassLoader) {
					DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
					for (Class<?> typeToMatch : typesToMatch) {
						dcl.excludeClass(typeToMatch.getName());
					}
				}
			}
		}

		// 获取BeanDefinition中所指定的beanClass属性的值,
		String className = mbd.getBeanClassName(); // 字符串 或者 #{xxx}
		if (className != null) {
			// className可以是Spring EL表达式,所以需要解析
			Object evaluated = evaluateBeanDefinitionString(className, mbd);
            // 如果 className 是Spring EL表达式,className 与 evaluated 会不相等的
			if (!className.equals(evaluated)) {
                // evaluated 类型是Class 直接返回
				if (evaluated instanceof Class) {
					return (Class<?>) evaluated;
				}
                // evaluated 类型是String 将 freshResolve 的值设置为 true
				else if (evaluated instanceof String) {
					className = (String) evaluated;
					freshResolve = true;
				}
				else {
					throw new IllegalStateException("Invalid class name expression result: " + evaluated);
				}
			}
			if (freshResolve) {
				if (dynamicLoader != null) {
					try {
                        // 使用类加载器加载类
						return dynamicLoader.loadClass(className);
					}
					catch (ClassNotFoundException ex) {
						if (logger.isTraceEnabled()) {
							logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
						}
					}
				}
				// 反射工具类加载Class对象
				return ClassUtils.forName(className, dynamicLoader);
			}
		}

		// 反射工具类加载Class对象
		return mbd.resolveBeanClass(beanClassLoader);
	}

resolveBeanClass 方法就是通过来判断 AbstractBeanDefinition 类中的 beanClass 属性,如果是 Class 就直接返回,如果不是就获取 beanClass 属性的值并将它转换为 Stirng 类型,然后对 className 做表达式解析。最后通过dynamicLoader.loadClass(className)加载 Class 对象,或者通过ClassUtils.forName(className, classLoader)加载 Class 对象。

prepareMethodOverrides

对通过XML定义的bean中的lookup-method和replace-method属性进行预处理

	try {
			// 对通过XML定义的bean中的lookup-method和replace-method方法进行预处理
			// 对于@Lookup注解标注的方法不在这里进行处理
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

进入AbstractBeanDefinition类的prepareMethodOverrides方法

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
		// Check that lookup methods exist and determine their overloaded status.
		//检查是否存在查找方法,并确定其重载状态。
		if (hasMethodOverrides()) {
			getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
		}
	}

进入AbstractBeanDefinition类的prepareMethodOverride方法

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() + "]");
		}
		else if (count == 1) {
			//标记 overloaded 暂未被被盖 避免参数类型检查的开销
			mo.setOverloaded(false);
		}
	}

该方法主要针对lookup-methodreplace-method做预处理,现在这两个属性用得比较少了。如果对这两个属性有兴趣,可以在 Spring 的官网进行查看: 点我前往 也可以移步前往: Spring源码(二—2)-lookup-method、replaced-method元素

resolveBeforeInstantiation

	try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			// 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);
		}

注意上面方法中有个if判断块,当经过前置处理后返回的结果如果不为空,那么会直接略过后续 bean 的创建而直接返回结果。当前 Bean 的创建流程结束,不会再往下执行 doCreateBean 函数。

进入 AbstractAutowireCapableBeanFactory类的resolveBeforeInstantiation方法

@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		// beforeInstantiationResolved的值只会为null或true
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				// 返回 Class 对象
				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;
	}

上述重点逻辑为如果实例化前方法返回的对象不为 null,则执行初始化后方法,并将经过初始后流程的Bean对象返回。

我们先来进入 AbstractAutowireCapableBeanFactory类的determineTargetType方法,该方法就是将 Class 对象加载出来。

	@Nullable
	protected Class<?> determineTargetType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
		// 获取resolvedTargetType属性,也相当于缓存,
		Class<?> targetType = mbd.getTargetType();
		if (targetType == null) {
			// 如果BeanDefinition中设置了factoryMethodName,那么就通过factoryMethodName来判断类型,
			// 否则获取AbstractBeanDefinition中的beanClass
			targetType = (mbd.getFactoryMethodName() != null ?
					getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
					resolveBeanClass(mbd, beanName, typesToMatch));
			if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
				// 将解析出来的类型记录到resolvedTargetType中
				mbd.resolvedTargetType = targetType;
			}
		}
        
		return targetType;
	}

AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsBeforeInstantiation实例化前方法

	@Nullable
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// 执行 postProcessBeforeInstantiation 方法,也就是 实例化前
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

注意:上述方法的方法名 applyBeanPostProcessors BeforeInstantiationBeforeInstantiation实例化前。首先获得所有的 BeanPostProcessor ,然后循环遍历判断是否实现了InstantiationAwareBeanPostProcessor,然后执行 postProcessBeforeInstantiation实例化前方法。如果 postProcessBeforeInstantiation方法返回了对象,也就是不返回 null,就执行 applyBeanPostProcessorsAfterInitialization初始化后方法。

AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsAfterInitialization初始化后方法

@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			// 执行postProcessAfterInitialization方法,也就是初始化后
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

也要注意该方法的方法名 applyBeanPostProcessorsAfterInitializationAfterInitialization初始化后。获取到所有的 BeanPostProcessor,然后循环每个BeanPostProcessorpostProcessAfterInitialization初始化后方法。如果postProcessAfterInitialization初始化后方法的返回值为 null就直接结束循环,进行返回。比如我有三个 BeanPostProcessor ,A、B、C,在执行A BeanPostProcessor 的时候,A的postProcessAfterInitialization方法返回了null,B、C两个BeanPostProcessor 不会再执行。AOP 也在此进行执行。

如果对于 BeanPostProcessor不熟悉的伙伴可以移步前往:Spring源码-BeanPostProcessor

doCreateBean

程序执行了 resolveBeforeInstantiation函数之后,如果返回的结果为 null,就需要执行 doCreateBean函数进行创建 Bean。

try {
			// 创建bean   Spring自带的创建bean的方法
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}

doCreateBean 函数的篇幅太长,将拆分几篇文章进行阅读。

  • 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。