【Spring源码分析】执行流程之非懒加载单例Bean的实例化逻辑

发布时间:2024年01月13日

在经过扫描操作获取到可用的 BeanDefinition 集后,接下来会进行实例化前的操作:将单例且非懒加载的BeanDefinition进行实例化放入单例池中。

下面是Bean的生命周期表,而接下来要源码分析的阶段是扫描完得到BeanDefinition后进行单例非懒加载Bean的处理,即对应着 DefaultListableBeanFactory 下的 preInstantiateSingletons() 方法。

在这里插入图片描述

preInstantiateSingletons() 源码分析

在扫描注册BeanDefinition时,除了把BeanDefinition注册到beanDefinitionMap中,还把beanName放入了beanDefinitionNames集合中。

	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("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) {
			// 获取合并后的BeanDefinition
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

			// 若该Bean是单例且不是懒加载的
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					// 获取FactoryBean对象
					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) {
							// 创建真正的Bean对象(getObject()返回的对象)
							getBean(beanName);
						}
					}
				}
				else {
					// 创建Bean对象
					getBean(beanName);
				}
			}
		}

		// 所有的非懒加载单例Bean都创建完了后
		// Trigger post-initialization callback for all applicable beans...
		// 所有非懒加载单例Bean创建完后的后置处理 SmartInitializingSingleton
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}
	}

合并 BeanDefinition getMergedLocalBeanDefinition

它是一个重载方法,其中 preInstantiateSingletons() 方法中调用的是下面这个:

	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 && !mbd.stale) {
			return mbd;
		}
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}

在这里插入图片描述

在这里插入图片描述

  • BeanFactory 是有分层的功能的,HierarchicalBeanFactory。
  • 合并父BeanDefinition,其中包括BeanDefinition本身定义的parent,若没有就得看其父上下文;
  • 合并完创建 RootBeanDefinition,然后再将本身的BeanDefinition将合并好的进行一些覆盖,最后即是getMergedLocalBeanDefinition 的结果;
  • mergedBeanDefinitions.put(beanName, mbd); 放入到 mergedBeanDefinitions 缓存中。

Bean 的分类【普通Bean、FactoryBean】

FactoryBean 示例:

@Component
public class MyFactoryBean implements FactoryBean {

	@Override
	public Object getObject() throws Exception {
		return new User();
	}

	@Override
	public Class<?> getObjectType() {
		return null;
	}
}

isFactoryBean(String name) 源码分析:

	@Override
	public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
		String beanName = transformedBeanName(name);

		// 首先从单例池中获取,判断单例池是否存在
		Object beanInstance = getSingleton(beanName, false);
		if (beanInstance != null) {
			return (beanInstance instanceof FactoryBean);
		}
		// No singleton instance found -> check bean definition.
		// 线工厂没这个Bean,父工厂判断一手
		if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
			// No bean definition found in this factory -> delegate to parent.
			return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
		}
		// 判断是否实现了 FactoryBean 接口
		// 然后以BeanDefinition 的 isFactoryBean 作为标志
		return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
	}

transformedBeanName 源码分析:

	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}

transformedBeanName 把 name 转换成普通的 beanName,即若有 FACTORY_BEAN_PREFIX & 前缀的话,就把 & 去掉,比如 &xxx 转换成 xxx,&&&&xxx 转换成 xxx。

在获取 bean 的时候也是通过 FACTORY_BEAN_PREFIX 把 bean 分为 FactoryBean 和普通 Bean 两种。

那接下来看看 FactoryBean 是怎么获取到其对应 Bean 的呢?

在这里插入图片描述

下面对 getObjectForBeanInstance 方法进行源码分析:

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		// 如果&xxx,那么就直接返回单例池中的对象
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		// 单例池中的对象不是FactoryBean,则直接返回
		// 即就是一普通对象了
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			// 从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);
			}
			// synthetic为true,表示这个Bean不是正常的一个Bean,可能只是起到辅助作用的,所以这种Bean就不用去执行PostProcessor了
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			// 调用 FactoryBean.getObject 方法去获取对应的 Object
			// 然后放入factoryBeanObjectCache缓存中
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

  • 先判断有无 FACTORY_BEAN_PREFIX 前缀,判断是否需要返回 FactoryBean,如果是直接返回;
  • 若并不是要返回 FactoryBean,即返回的是普通对应,就判断从单例池中获取到的实例是否实现了 FactoryBean;
  • 若没实现直接作为普通对象进行返回;
  • 若实现了即调用 getObject 方法进行返回(先会去factoryBeanObjectCache缓存中找),并存入 factoryBeanObjectCache 缓存中。

测试:

public class Test {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext
				context = new AnnotationConfigApplicationContext();
		context.register(AppConfig.class);
		context.refresh();
		
		System.out.println(context.getBean("user", User.class));// com.powernode.User@61ca2dfa
        System.out.println(context.getBean("myFactoryBean"));// com.powernode.User@4b53f538
		System.out.println(context.getBean("&&&&myFactoryBean"));// com.powernode.MyFactoryBean@4b53f538
	}

}

若想提前放入 factoryBeanObjectCache 缓存中,可以实现 SmartFactoryBean 接口,然后重写 isEagerInit() 若返回的是 true,即会提前调用 getBean(beanName) ,这样就放入缓存了,下次取就直接走缓存了,不会去调用 getObject 方法了。

在这里插入图片描述

Bean 的创建逻辑

上面有提到从单例池中获取到了对于bean的情况下进行的处理,若单例池中没有这个Bean呢?它是如何创建并放入到单例池的呢?接下来源码分析对应的逻辑:

在 getBean 中,首先是从单例池去获取对应的 Bean,若获取不到则会去尝试创建,去获取的操作上述阐述了,这里阐述一下创建的逻辑,其实现都归于 doGetBean 方法。

下面是其核心代码(含注释分析):

			/**
				这里只是 else 的逻辑,就是获取对应bean的时候,在单例池中找不着,需要去尝试创建的代码
			**/
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			// 这里是去排除循环引用
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			// 尝试先让父 BeanFactory 去 getBean 获取对应的 Bean
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				// &&&&xxx---->&xxx
				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);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}
			
			// 接下来是去操作 @DependsOn 注解的关系
			// 这里是强依赖关系,若是使用@DependsOn注解产生了循环依赖的话,那是无法解决的
			StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
					.tag("beanName", name);
			try {
				if (requiredType != null) {
					beanCreation.tag("beanType", requiredType::toString);
				}
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

				// 检查BeanDefinition是不是Abstract的
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					// dependsOn表示当前beanName所依赖的,当前Bean创建之前dependsOn所依赖的Bean必须已经创建好了
					for (String dep : dependsOn) {
						// beanName是不是被dep依赖了,如果是则出现了循环依赖
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						// dep被beanName依赖了,存入dependentBeanMap中,dep为key,beanName为value
						registerDependentBean(dep, beanName);

						// 创建所依赖的bean
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance.
				// 根据 Scope 的类型去创建 Bean
				if (mbd.isSingleton()) {
                    // getSingleton 方法很简单,就是将 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;
						}
					});
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				else if (mbd.isPrototype()) {// 如果是多例的话就直接创建一个Bean返回,没有后续操作
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
				else {
                    // 这个是处理其他 Scope 的,如 web 中的 request、session、application
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean ′" + beanName + "'");
					}
					Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {  // session.getAttriute(beaName)  setAttri
                        // 这实现很简单,就是通过 Lambda 那个返回的bean,将其创建后放到对应作用域
                        // 如果作用域本身就有这个 bean 的话就直接返回
                        // 达到web作用域的bean单一的效果
                        // 即通过 setAttribute和getAttribute进行实现的
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
				beanCreation.tag("exception", ex.getClass().toString());
				beanCreation.tag("message", String.valueOf(ex.getMessage()));
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
			finally {
				beanCreation.end();
			}

在创建 Bean 时,会对不同Bean的作用域进行逻辑处理,不同作用域的创建形式有一定的差异,在配置 Bean 的作用域的时候,除了可以配置 singleton和 protocol,还可以配置适用 Web(MVC)的Bean 的作用域,如 request(RequestScope),session(SessionScope),application(ApplicationScope),这些作用域。

在这里插入图片描述

阐述了半天,不管是哪种作用域,其核心都是要创建出bean,而创建的逻辑都归功于 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;

		// 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了,确保beanClass被加载了
		// 加载beanClass,从而得到对应的 Class 对象
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		// 方法覆盖,和 @Lookup 注解有一定的关系
		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.
			// 实例化前
			// InstantiationAwareBeanPostProcessor
			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.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);
		}
	}

实例化前源码分析

下面是实例化前的代码截取出来:

			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			// 实例化前
			// InstantiationAwareBeanPostProcessor
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
  • 就是说如果 resolveBeforeInstantiation 中直接返回了对应的实例,就直接返回,那么后续Bean创建的生命周期自然不会进行了,如果没有的话就继续往下执行,这就是实例化前所做的操作。

那下面对 resolveBeforeInstantiation 方法进行分析:

	@Nullable
	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.
			// synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { // BeanPostProcessorCache 中的 instantiationAware 不能为空
				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;
	}

这里涉及到一种 BeanPostProcessor,在 BeanPostProcessor 接口中定义了初始化前和初始化后的功能,那么它有一些子类,在这俩功能上提供了其他功能,这里涉及到 InstantiationAwareBeanPostPostProcessor ,它在初始化前和初始化后的功能之后还提供了实例化前和实例化后功能。

在 Spring 加载的过程中会把所有的BeanPostProcessor放入到 beanPostProcessors 集合中。

然后调用 AbstractBeanFactory#getBeanPostProcessorCache 方法后会将其进行分类,然后封装成 BeanPostProcessorCache 实例。

在这里插入图片描述

分成这四类不同的后置处理器都有对应的用法,在 Bean 生命周期的不同阶段会进行调用。

BeanPostProcessorCache 内部实现很简单,就是各个BeanPostProcessor的集合,AbstractBeanFactory 中的一个静态类:

在这里插入图片描述

把流程解读一遍:

  • 判断是否是合成的且存在 instantiationAware;

  • 然后遍历处理这些后置处理器:

    • 在这里插入图片描述
  • 若是实例化前返回了 Bean 则处理实例化后的后置处理器,处理完把Bean给返回。

虽然 Spring 提供了这个实例化前的可控操作,但是在实际运用中好像没啥软用

总结

  • getBean->doGetBean
  • 从单例池中获取,获取到实例后判断是返回FactoryBean还是普通Bean;
  • 若没获取到则走创建逻辑:
    • 先让父BeanFactory#getBean
    • 排除@DependsOn注解引起的依赖,提前getBean()所依赖的;
    • 判断Scope Bean的作用域,单例呢就是创建出来放入单例池,多例就是创建之后直接返回,web对应的作用域就是创建Bean之后,放入到对应的作用域中,例如RequestScope则通过#setAttribute放入到对应请求域中;
    • 其创建Bean实例的方法是通过 createBean 方法.createBean 方法对应流程如下:
      • 加载对应类
      • InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(),看看实例化前是否有实例化操作,有就不用往下了。
      • 实例化
      • 对合并的 BeanDefinition 进行后置处理:MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition()
      • AbstractAutowireCapableBeanFactory#populate属性填充
        • InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
        • 依赖注入
          • 属性赋值(Spring自带的依赖注入)
          • InstantiationAwareBeanPostProcessor#postProcessProperties()(@Autowired、@Value-----AutowiredAnnotationBeanPostProcessor;@Resource、@PostConstruct、@PreDestroy----------CommonAnnotationBeanPostProcessor
      • 初始化
        • 执行 Aware 方法,BeanNameAware、BeanClassLoaderAware、BeanFactoryAware;ApplicationContextAwareProcessor 中还有很多 Aware 判定,比如 ApplicationContextAware。
        • 初始化前 BeanPostProcessor#postProcessBeforeInitialization
        • 初始化 InitializingBean#afterPropertiesSet
        • 初始化后 BeanPostProcessor#postProcessAfterInitialization
文章来源:https://blog.csdn.net/qq_63691275/article/details/135567702
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。