Spring源码(三) ———创建实例对象推断构造方法

Spring源码(三) ——创建实例对象推断构造方法

之前的Spring源码(一)——Bean生命周期源码解读文章,讲了下Bean的生命周期以及ApplicationContext构造方法的大致逻辑,其中最核心的是refresh方法,但是里面有些方法没有细说。比如invokeBeanFactoryPostProcessors(beanFactory),
registerBeanPostProcessors(beanFactory),
finishBeanFactoryInitialization(beanFactory)
这三个方法 是refresh 中想当重要的方法。而我们的上一篇Spring源码(二)——配置类解析以及扫描Bean对象说了下invokeBeanFactoryPostProcessors方法。

今天我们就详细看看与创建对象相关的方法:finishBeanFactoryInitialization()。

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
//注意这个方法值实例化所有的非懒加载的单例

我们从finishBeanFactoryInitialization这个方法下钻进去看看,这个方法做了什么事情。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// 判断是否有线程安全的类型转化器,如果没有创建一个
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		//如果没有bean后置处理器,则注册一个默认的嵌入式值解析器
		//(例如一个property留出的配置符bean)之前注册过:
		//主要用于注释属性值的解析。
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		//提前初始化LoadTimeWeaverAware bean以允许提前注册它们的转换器。
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// 停止使用临时ClassLoader进行类型匹配
		beanFactory.setTempClassLoader(null);

		// 允许缓存所有bean定义元数据。
		beanFactory.freezeConfiguration();

		// 实例化所有剩余的(非lazy-init)单例
		beanFactory.preInstantiateSingletons();
	}

我们继续下钻看看 beanFactory.preInstantiateSingletons();

@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isDebugEnabled()) {
			logger.debug("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

首先这个方法就先去获取所有的beanName.

List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

然后遍历beanName.

  1. 先从容器中获取beanName 对应的beanDefinition.**注意这里获取的是在扫描部分合并后的BeanDefinition,也就是RootBeanDefinition类型。如果没有就获取原beanDefinition,将这个原BeanDefinition封装成RootBeanDefinition类型.

     protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
     		// Quick check on the concurrent map first, with minimal locking.
     		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
     		if (mbd != null) {
     			return mbd;
     		}
     		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
     	}
    
  2. 判断是否不是抽象的,是否是单例,是否非懒加载。

     if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    
  3. 判断是否是工厂bean。

    if (isFactoryBean(beanName)) {
    
  4. 如果是工厂bean,调用getBean方法。但是beanName前面加上一个前缀 & 这个复符号。如果不是就直接使用 beanName 去调用getBean方法。

     if (isFactoryBean(beanName)) {//是工厂bean
     			// FACTORY_BEAN_PREFIX  == &
     			Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
     			if (bean instanceof FactoryBean) {
     				FactoryBean<?> factory = (FactoryBean<?>) bean;
     				boolean isEagerInit;
     				//判断是否马上初始化,
     				if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
     					isEagerInit = AccessController.doPrivileged(
     							(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
     							getAccessControlContext());
     				}
     				else {
     					isEagerInit = (factory instanceof SmartFactoryBean &&
     							((SmartFactoryBean<?>) factory).isEagerInit());
     				}
     				if (isEagerInit) {//是,初始化。
     					getBean(beanName);
     				}
     			}
     }
     else {//不是工厂bean,是普通bean
     		getBean(beanName);
     	}
    

最后的初始化
在上面遍历完beanNames后,Spring 还会在遍历一次,这次是获取实例,判断实例是否实现了SmartInitializingSingleton接口,如果实现了调用afterSingletonsInstantiated方法。

		//触发所有适用bean的后初始化回调…
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}

上面是创建Bean的大概流程,我们相信看看getBean方法,如何去创建bean对象。

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
				//省略的代码。。。。。。。。。。。
				// Create bean instance.
				if (mbd.isSingleton()) {
					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;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
		//省略的代码。。。。。。。。。。。
		return (T) bean;
	}

如果是单例,调用getSingleton ,如果是空,调用==createBean(beanName, mbd, args)==方法

@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		//省略的代码。。。。。。

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			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 {
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		//省略的代码。。。。。。
	}

在createBean这个方法里面有这样一句代码。

	Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

这个代码就是在实例化之前会调用的方法。只要你的类实现了InstantiationAwareBeanPostProcessor接口并且实现了postProcessBeforeInstantiation方法。 他这个接口里面还有postProcessAfterInstantiation 实例化后方法。

继续我们看看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) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
		//省略的代码。。。。。。

		// 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.
		Object exposedObject = bean;
		try {
			//依赖注入
			populateBean(beanName, mbd, instanceWrapper);
			//初始化
			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);
			}
		}
	//省略的代码。。。。。。 
	//循环依赖的处理
	//省略的代码。。。。。。

		return exposedObject;
	}
重点来了 ,推断构造方法。
	if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}

下钻这个方法看看。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// 解析类信息
		Class<?> beanClass = resolveBeanClass(mbd, beanName);
		//如果这个类不是public 修饰的报错。
		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) {
		//判断循环创建中是否有这个实例,返回这个实例,没有返回NullBean;
			return obtainFromSupplier(instanceSupplier, beanName);
		}
		//判断工厂方法是否不为空
		if (mbd.getFactoryMethodName() != null) {
			//使用工厂方法去创建实例。
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		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);
		}

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

然后将所有的构造方法传入autowireConstructor f方法中。

if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			Object[] argsToResolve = null;
			synchronized (mbd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}

argsToUse这个属性可以设置成为 能被使用的参数 ,
explicitArgs 这个理解为 传入的参数。
这一块判断传入的参数是否为空,如果不为空设置 能被使用的参数为传入的参数。
如果为空 ,判断factory中看看缓存中是否有缓存构造方法以及参数信息。如果有获取参数信息这是未 能被使用的参数。

当在这一步能获取到构造方法以及参数的时候

如果能从缓存中获取到构造方法以及参数。后面就不需要走了。直接使用从缓存中获取的构造方法与参数去实例化对象。

当在这一步不能获取到构造方法以及参数的时候
	AutowireUtils.sortConstructors(candidates);

会调用这个方法,将所有的构造方法,参照参数个数降序排序。
然后遍历构造方法的集合。
然后下面这一段会对构造方法进行一个打分。如果分数越低优先级越高。

int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// Choose this constructor if it represents the closest match.
				if (typeDiffWeight < minTypeDiffWeight) {
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}

总结:

autowireConstructor()

  1. 先检查是否指定了具体的构造方法和构造方法参数值,或者在BeanDefinition中缓存了具体的构造方法或构造方法参数值,如果存在那么则直接使用该构造方法进行实例化
  2. 如果没有确定的构造方法或构造方法参数值,那么
    a. 如果没有确定的构造方法,那么则找出类中所有的构造方法
    b. 如果只有一个无参的构造方法,那么直接使用无参的构造方法进行实例化
    c. 如果有多个可用的构造方法或者当前Bean需要自动通过构造方法注入
    d. 根据所指定的构造方法参数值,确定所需要的最少的构造方法参数值的个数
    e. 对所有的构造方法进行排序,参数个数多的在前面
    f. 遍历每个构造方法
    g. 如果不是调用getBean方法时所指定的构造方法参数值,那么则根据构造方法参数类型找值
    h. 如果时调用getBean方法时所指定的构造方法参数值,就直接利用这些值
    i. 如果根据当前构造方法找到了对应的构造方法参数值,那么这个构造方法就是可用的,但是不一定这个构造方法就是最佳的,所以这里会涉及到是否有多个构造方法匹配了同样的值,这个时候就会用值和构造方法类型进行匹配程度的打分,找到一个最匹配的

@Bean的情况

首先,Spring会把@Bean修饰的方法解析成BeanDefinition:如果方法不是static的,那么解析出来的BeanDefinition中:factoryBeanName为AppConfig所对应的beanName,比如"appConfig"factoryMethodName为对应的方法名,比如"aService"factoryClass为AppConfig.class如果方法是static的,那么解析出来的BeanDefinition中:factoryBeanName为nullfactoryMethodName为对应的方法名,比如"aService"factoryClass也为AppConfig.class在由@Bean生成的BeanDefinition中,有一个重要的属性isFactoryMethodUnique,表示factoryMethod是不是唯一的,在普通情况下@Bean生成的BeanDefinition的isFactoryMethodUnique为true,但是如果出现了方法重载,那么就是特殊的情况,比如:

	@Bean
	public static AService aService(){
		return new AService();
	}

	@Bean
	public AService aService(BService bService){
		return new AService();
	}

虽然有两个@Bean,但是肯定只会生成一个aService的Bean,那么Spring在处理@Bean时,也只会生成一个aService的BeanDefinition,比如Spring先解析到第一个@Bean,会生成一个BeanDefinition,此时isFactoryMethodUnique为true,但是解析到第二个@Bean时,会判断出来beanDefinitionMap中已经存在一个aService的BeanDefinition了,那么会把之前的这个BeanDefinition的isFactoryMethodUnique修改为false,并且不会生成新的BeanDefinition了。

并且后续在根据BeanDefinition创建Bean时,会根据isFactoryMethodUnique来操作,如果为true,那就表示当前BeanDefinition只对应了一个方法,那也就是只能用这个方法来创建Bean了,但是如果isFactoryMethodUnique为false,那就表示当前BeanDefition对应了多个方法,需要和推断构造方法的逻辑一样,去选择用哪个方法来创建Bean。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值