当前位置: 首页 > article >正文

Spring之Bean的获取过程

大致过程总结

创建Bean的流程
1、将传入的name,进行转化,获取到BeanName 
	a.传入的有可能是别名,在aliasMap中获取到真实的BeanName
	b、传入的有可能携带&符号,需要将带&的name去处。
2、尝试先从单例池中获取(三七法则,绝大部分的Bean是单例的)
	a、如果获取成功,判断这个Bean是否在创建中,如果是在创建中则抛出在创建中的错误。
	b、没有在创建中,则需要判断是否为factoryBean,如果是FactoryBean,需要获取getObject()方法中的返回的对象。
3.如果在单例池中不存在,则需要正式开始创建Bean了。
	1、从mergedBeanDefinitions获取合并后的BeanDefinition。
	2、检查BeanDefinition是否为抽象的,如果为抽象的需要抛出异常。
	3、获取Bean通过@DependsOn注解依赖的Bean对象。如果存在,需要判断是否存在相互依赖的关系
		1、假如现在正在创建A对象,A对象依赖B对象,而B对象又通过@DependsOn依赖了A对象,此时需要抛出异常。这种相互依赖无法解决。
		2、假如现在正在创建A对象,A对象依赖B对象,但B对象没有依赖A对象,则开始创建B对象。

	4、将依赖关系存入到dependentBeanMap(被哪些Bean依赖)、dependenciesForBeanMap(依赖了哪些Bean)
	5、单例Bean创建
		1、尝试在单例池中获取,如果单例池中为空,则开始创建。
		2、实例化前【Object bean = resolveBeforeInstantiation(beanName, mbdToUse)】
			1、先判断是否有实现InstantiationAwareBeanPostProcessor的类,如果存在则调用【postProcessBeforeInstantiation】方法。
			2、如果实例化前有返回值,不为null,则直接调用实例化后的方法【applyBeanPostProcessorsAfterInitialization】。
		3、如果实例化前返回了Bean对象,不为null,则直接把结果返回。
		4、初始化【Class<?> resolvedClass = resolveBeanClass(mbd, beanName)】通过ClassLoader加载类,获取类对象。
		5、复制BeanDefinfition,同时设置BeanClass。
		6、判断是否实现了【MergedBeanDefinitionPostProcessor】接口,如果实现了则调用【postProcessMergedBeanDefinition】方法。这个方法可以在属性填充之前,进行手动属性复制。
		7、属性填充,先判断用户是否手动填充了属性的值,如果存在则会用手动填充的值。
		8、判断是否实现了【Aware】接口,调用对应的方法,进行属性设置。
		9、实例化前
			1、调用【postProcessBeforeInitialization】方法。
		10、实例化
			1、判断Bean是否实现了【InitializingBean】接口,调用【afterPropertiesSet】方法,
			2、判断是否制定了初始化的方法【initMethodName】,如果指定了,调用该方法。
		11、实例化后
			1、调用【postProcessAfterInitialization】方法
		12、处理Bean销毁方法。
		13、返回Bean
	6、将获取到的Bean进行判断,是否为FactoryBean
		1、如果是;尝试从factoryBeanObjectCache缓存中获取,将结果返回,如果获取失败,则调用【getObject()】创建Bean。
		2、如果不是,则直接返回。
4、将Bean添加到单例池中。
		

1、获取Bean的三种方式

1、public Object getBean(String name)
2、public <T> T getBean(String name, Class<T> requiredType)
3、public Object getBean(String name, Object... args) 
无论哪种获取Bean的方式,最终都是调用的protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)这个方法。
  1. protected String transformedBeanName(String name)
    在这个方法里面,首先进行的就是根据输入的name,获取到真实的BeanName。这个发方法大致会进行两个判断
    a、首先判断这个name上是否含有&符号,会循环将&符号去除。
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;
		});
	}

b、通过public String canonicalName(String name)方法,将真实的BeanName获取到。

public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

由于一个Bean可以被配置多个别名,而BeanDefinition只会对应一个BeanName,所以需要后去到这个BeanName。

由于大部分的Bean是单例的,所以会先尝试从单例池中获取。
1、如果可以获取到,就会判断是否为factoryBean,从而进行转化,获取到对应的Bean对象。
2、如果没有获取到,则开始创建需要开始创建Bean。

在创建之前,会先判断由@DependsOn依赖的Bean,之间是是否存在相互依赖问题。

String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						// 如果存在相互依赖的情况,抛出错误
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						// 添加相互的依赖关系
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

在这个方法里面,运用了两个Map作为缓存,以下做了解释

	// 被依赖的Map
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

	// 依赖的Map
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

2、根据作用域,进行创建,在此我们只介绍单例Bean的创建过程。

// 创建单例Bean
				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);
				}
  1. 同样的,先从单例池中尝试获取Bean。如果获取到了,则直接返回。
  2. 没有获取到,开始正式的创建。
  3. 先进性实例化前的操作

3、实例化前

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;
	}

在这个方法中,首先会调用applyBeanPostProcessorsBeforeInstantiation这个方法,此方法会调用postProcessBeforeInstantiation方法。

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

调用BeanPostProcessor.postProcessBeforeInstantiation()方法
如果如果返回值不为空,则调用完成实例化后的方法后,则直接返回对象。

4、实例化对象AbstractAutowireCapableBeanFactory.doCreateBean->createBeanInstance()

// 通过类加载器,获取类对象
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 推断构造方法,获取创建Bean的构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 实例化
instantiateBean(beanName, mbd)

5、属性填充 populateBean(beanName, mbd, instanceWrapper);

1、实例化后

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						return;
					}
				}
			}
		}

调用BeanPostProcessor.postProcessAfterInstantiation()方法

2、执行属性填充 applyPropertyValues(beanName, mbd, bw, pvs);

6、初始化AbstractAutowireCapableBeanFactory.initializeBean()

1、Aware回调

private void invokeAwareMethods(String beanName, Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}
  1. 如果实现了BeanNameAware接口,那么将会把BeanName返回。
  2. 如果实现了BeanClassLoaderAware接口,那么将会把加载Bean的类加载器返回。
  3. 如果实现了BeanFactoryAware接口,那么将会把创建Bean的Bean工厂返回。

2、初始化前 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization()

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

调用BeanPostProcessor.postProcessBeforeInitialization()方法

3、初始化 AbstractAutowireCapableBeanFactory.invokeInitMethods()

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}
  1. 判断是否实现了InitializingBean接口,如果实现了,执行afterPropertiesSet()方法。
  2. 判断是否设置了初始化方法发,执行初始化方法invokeCustomInitMethod(beanName, bean, mbd);

7、初始化后AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization()

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

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

调用BeanPostProcessor.postProcessAfterInitialization()方法。

8、处理销毁Bean的方法 AbstractAutowireCapableBeanFactory.registerDisposableBeanIfNecessary()

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
			if (mbd.isSingleton()) {
				// Register a DisposableBean implementation that performs all destruction
				// work for the given bean: DestructionAwareBeanPostProcessors,
				// DisposableBean interface, custom destroy method.
				registerDisposableBean(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
			else {
				// A bean with a custom scope...
				Scope scope = this.scopes.get(mbd.getScope());
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
				}
				scope.registerDestructionCallback(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
		}
	}

9、将单例Bean加入单例池中。

protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

以上就是创建Bean的完整流程,有兴趣的可以在评论区交流。


http://www.kler.cn/a/7162.html

相关文章:

  • 蓝队基础之网络七层杀伤链
  • Linux 命令 | 每日一学,文本处理三剑客之awk命令实践
  • 矩阵的对角化特征值分解
  • 问题分析与解决:Android开机卡动画问题分析
  • Go 语言切片初始化与性能优化:使用 cap 参数的重要性
  • 大数据-226 离线数仓 - Flume 优化配置 自定义拦截器 拦截原理 拦截器实现 Java
  • LC-1125. 最小的必要团队(状态压缩 + 0-1背包)
  • React 组件通信
  • PCL 非线性最小二乘法拟合圆柱
  • 4.5---Spring框架之Spring的自动装配(复习版本)
  • 2023年第十四届蓝桥杯JAVA B组题目
  • SpringMVC的全注解开发
  • MySQL开发02-数据库设计
  • Json交互处理_stata交互项检验
  • Huananzhi X99-AD3 Intel E5-2696v3黑苹果efi引导文件
  • Java 垃圾收集器
  • php防止表单重复提交的几种方法
  • 为什么要进行自动化测试,又有哪些需要注意的
  • rk3568 Android 添加IR遥控器
  • 交友项目【手机号登录注册功能】实现
  • MapGIS 6.7安装方法教程
  • (一)MyBatis源码阅读:明晰项目结构
  • 乐鑫 × 全国大学生物联网设计竞赛|探究基于 ESP32-S3 的农业革新应用
  • 【SQL开发实战技巧】系列(四十六):Oracle12C常用新特性☞会话级序列及数据泵(DataPump增强)支持像表一样导出视图
  • 单例设计模式
  • VS2019使用VLD(Visual Leak Detector)检测CPP内存泄漏