一起学SF框架系列5.4-模块Beans-DefaultListableBeanFactory

这篇具有很好参考价值的文章主要介绍了一起学SF框架系列5.4-模块Beans-DefaultListableBeanFactory。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在生成ApplicationContext过程中,AbstractRefreshableApplicationContext.refreshBeanFactory()完成旧BeanFactory关闭,创建新的BeanFactory,即new DefaultListableBeanFactory(…)。然后bean实例化时调用本类的preInstantiateSingletons方法。

类作用

BeanFactory作用是初始化和管理普通bean,因此DefaultListableBeanFactory是实现框架核心功能(IoC)的核心类。

类关系图

一起学SF框架系列5.4-模块Beans-DefaultListableBeanFactory
DefaultListableBeanFactory类关系图比较复杂,我们从顶向下梳理:

接口定义说明

AliasRegistry:顶层接口,别名注册表接口,定义了管理bean的别名和名称映射关系的基本方法,如注册registerAlias(String name, String alias)、获取(getAliases(String name))和销毁(removeAlias(String alias))。

SingletonBeanRegistry:顶层接口,单实例bean注册表接口,定义了管理单实例Bean的基本方法,如注册(registerSingleton(String beanName, Object singletonObject))和获取(getSingleton(String beanName)。

BeanFactory:顶层接口,定义了访问bean容器中bean的基本方法,只包括get或判断(如is、contain)类方法。完全不包括BeanFactory是如何初始化并管理bean的方法。从使用者来说,只是按需使用即可,不关注如何实现。

HierarchicalBeanFactory:继承BeanFactory,仅提供访问继承关系BeanFactory的方法,包括etParentBeanFactory()和containsLocalBean(String name)(当前BeanFactory(不是父BeanFactory)是否包含名为name的bean)。

ListableBeanFactory:是BeanFactory接口扩展,定义通过枚举其所有bean实例的方法来访问bean,而不是通过getBean(String beanName)这种单个按名称查找bean。

AutowireCapableBeanFactory:是BeanFactory接口扩展,定义具备自动装配能力的BeanFactory的实现方法。

ConfigurableBeanFactory:定义普通配置模式下BeanFactory的实现方法,如解析bean配置和bean的初始化。

ConfigurableListableBeanFactory:继承了接口ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory,并增加定义了分析和修改bean定义以及预实例化单实例bean的方法。

BeanDefinitionRegistry:BeanDefinition注册表接口,定义对BeanDefinition(即bean的元数据)进行管理的方法。

SimpleAliasRegistry

实现接口AliasRegistry(bean alias存取及相关操作)。

DefaultSingletonBeanRegistry

主要实现单实例bean的缓存池,包括bean依赖关系管理(关系注册和销毁)。本类方法大量采用了synchronized存取缓存池(集合)。
继承于SimpleAliasRegistry,并实现接口SingletonBeanRegistry(单实例bean的存取及相关操作)

FactoryBeanRegistrySupport

单实例bean管理中用到的关于factoryBean的相关方法实现。

AbstractBeanFactory

AbstractBeanFactory主要实现ConfigurableBeanFactory接口功能。BeanFactory大多数功能在该类实现,但核心方法createBean需在子类实现。

AbstractAutowireCapableBeanFactory

继承AbstractBeanFactory,并实现接口AutowireCapableBeanFactory,即自动装配相关功能在该类实现。
核心方法createBean在该类实现。

DefaultListableBeanFactory

继承AbstractAutowireCapableBeanFactory,主要实现接口ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable。其中ConfigurableListableBeanFactory接口中的AutowireCapableBeanFactory, ConfigurableBeanFactory均在祖先类实现了,因此只需实现ListableBeanFactory接口方法。BeanDefinitionRegistry接口全部在这里实现。

类实现

DefaultListableBeanFactory继承于AbstractAutowireCapableBeanFactory,大多数bean的创建、初始化等实现已在祖先类实现。本类主要实现BeanDefinitionRegistry接口和ListableBeanFactory接口。

DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory)

DefaultListableBeanFactory构建类,实际构建在父类AbstractAutowireCapableBeanFactory完成,核心动作是动态生成子类的对象instantiationStrategy(CglibSubclassingInstantiationStrategy 用cgilib动态创建子类)。
DefaultListableBeanFactory构建代码:

	public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		super(parentBeanFactory);
	}

父类AbstractAutowireCapableBeanFactory构建代码:

	public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
		this();
		setParentBeanFactory(parentBeanFactory);
	}
	public AbstractAutowireCapableBeanFactory() {
		super();
		ignoreDependencyInterface(BeanNameAware.class);
		ignoreDependencyInterface(BeanFactoryAware.class);
		ignoreDependencyInterface(BeanClassLoaderAware.class);
		//bean实例化器 
		this.instantiationStrategy = new CglibSubclassingInstantiationStrategy();
	}

注1:CglibSubclassingInstantiationStrategy是Bean真正初始化类,详见https://blog.csdn.net/davidwkx/article/details/131053503

preInstantiateSingletons

该方法是启动过程中spring对单实例bean初始化的入口。

	@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) {
			//所有bean定义都统一成RootBeanDefinition 注1
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//非抽象类、非延迟加载且是Singleton的bean进行初始化
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				//FactoryBean初始化
				if (isFactoryBean(beanName)) {
					//getBean通过有无前缀FACTORY_BEAN_PREFIX 识别是否FactoryBean 注2
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					//FactoryBean中bean默认是延迟创建的,如果FactoryBean实现了SmartFactoryBean,重载isEagerInit()返回true,则表示立即对FactoryBean中的bean进行创建 注3
					if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
						//FactoryBean创建bean
						getBean(beanName);
					}
				}
				//普通bean初始化
				else {
					getBean(beanName);
				}
			}
		}

		//如果bean实现了SmartInitializingSingleton接口,则在初始化后回调afterSingletonsInstantiated
		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				smartSingleton.afterSingletonsInstantiated();
				smartInitialize.end();
			}
		}
	}

注1:bean定义相关见:
注2:getBean(beanName)在AbstractBeanFactory实现,实际是调用AbstractBeanFactory.doGetBean(beanName, null, null, false),详见:https://blog.csdn.net/davidwkx/article/details/130963899
注3:如果beanName是FactoryBean的名称,getBean(“&”+beanName) 是获取 FactoryBean 本身,而getBean(beanName) 获取的是 FactoryBean 创建出来的 bean 实例。

resolveDependency / doResolveDependency

解析指定beanName对应的属性,并将解析到的属性名放入autowiredBeanNames,根据类型查找依赖关系文章来源地址https://www.toymoban.com/news/detail-479367.html

	@Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		if (Optional.class == descriptor.getDependencyType()) {
			// Optional类型的注入处理
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			// ObjectFactory类型的注入处理
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			// Jsr330注解的注入处理
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
				//非延迟加载的常规注入处理
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

	@Nullable
	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			// @Value注解的注入
			Class<?> type = descriptor.getDependencyType();
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String strValue) {
					// 占位符解析
					String resolvedValue = resolveEmbeddedValue(strValue);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					// EL表达式
					value = evaluateBeanDefinitionString(resolvedValue, bd);
				}
				// 转换类型
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					// A custom TypeConverter which does not support TypeDescriptor resolution...
					return (descriptor.getField() != null ?
							converter.convertIfNecessary(value, type, descriptor.getField()) :
							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}

			//解析多个bean,例如List、set、Map
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			// 依赖查询
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}
			String autowiredBeanName;
			Object instanceCandidate;
			// 如果有多个匹配的Bean,就根据方法名称进行匹配
			if (matchingBeans.size() > 1) {
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
						// In case of an optional Collection/Map, silently ignore a non-unique case:
						// possibly it was meant to be an empty collection of multiple regular beans
						// (before 4.3 in particular when we didn't even look for collection beans).
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

到了这里,关于一起学SF框架系列5.4-模块Beans-DefaultListableBeanFactory的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【蓝牙系列】蓝牙5.4到底更新了什么(2)

      上一篇文章讲了蓝牙5.4的PAwR特征,非常适合应用在电子货架标签(ESL)领域, 但是实际应用场景中看,只有PAwR特性是不够的,如何保证广播数据的安全性,如何动态调节广播的编码方式以达到最优的功耗。 这就需要用到本章需要介绍的蓝牙5.4的几个新特性。 下面再回

    2024年01月20日
    浏览(39)
  • 【蓝牙系列】蓝牙5.4到底更新了什么?(1)--- PAwR

      蓝牙技术联盟最近发布了蓝牙5.4的核心规范,蓝牙5.4规范的主要改进之一就是实现了单个接入点与数千个终端节点进行双向无连接通信, 这一特性主要是针对电子货架标签(Electronic Shelf Label,ESL)市场。   电子货架标签是一种带有信息收发功能的电子版的价签显示装

    2024年02月08日
    浏览(38)
  • 一起学Elasticsearch系列-索引管理

    本文已收录至Github,推荐阅读 👉 Java随想录 微信公众号:Java随想录 在Elasticsearch中,索引是对数据进行组织和存储的基本单元。索引管理涉及创建、配置、更新和删除索引,以及与索引相关的操作,如数据导入、搜索和聚合等。这些关键任务直接影响着系统性能、数据可用

    2024年02月02日
    浏览(45)
  • 一起学习ETCD系列——简单安装

    在微服务中服务发现是必不可少的,此时ETCD中间件就是一种可选项,其实ETCD除了服务发现功能,还有: 元数据存储,比如存储服务配置等数据,以实现配置中心化,进行统一的,有版本记录的变更管理; 分布式锁; 选主,master-slave的软件架构中可以通过etcd快速实现选主的

    2024年01月25日
    浏览(44)
  • 一起学Elasticsearch系列-模糊搜索

    本文已收录至Github,推荐阅读 👉 Java随想录 微信公众号:Java随想录 在 Elasticsearch 中,模糊搜索是一种近似匹配的搜索方式。它允许找到与搜索词项相似但不完全相等的文档。 前缀匹配通过指定一个前缀值,搜索并匹配索引中指定字段的文档,找出那些以该前缀开头的结果

    2024年02月01日
    浏览(46)
  • 一起学Elasticsearch系列-并发控制

    本文已收录至Github,推荐阅读 👉 Java随想录 微信公众号:Java随想录 ES的并发控制是一种机制,用于处理多个同时对同一份数据进行读写操作的情况,以确保数据的一致性和正确性。 实现并发控制的方法主要有两种:悲观锁和乐观锁。 悲观锁是一种并发控制机制,它基于一

    2024年04月27日
    浏览(43)
  • 一起学Elasticsearch系列-核心概念

    本文已收录至Github,推荐阅读 👉 Java随想录 微信公众号:Java随想录 开个新的坑,创作关于Elasticsearch的系列文章 首先,让我们简单的了解一下Elasticsearch: Elasticsearch是一个开源的搜索和分析引擎,支持近实时的大数据存储、搜索和分析。它基于Apache Lucene项目,提供全文搜索

    2024年02月01日
    浏览(49)
  • 一起学Elasticsearch系列-聚合查询

    本文已收录至Github,推荐阅读 👉 Java随想录 微信公众号:Java随想录 聚合查询是 Elasticsearch 中一种强大的数据分析工具,用于从索引中提取和计算有关数据的统计信息。聚合查询可以执行各种聚合操作,如计数、求和、平均值、最小值、最大值、分组等,以便进行数据汇总和

    2024年01月22日
    浏览(50)
  • 【一起撸个DL框架】3 前向传播

    CSDN个人主页:清风莫追 欢迎关注本专栏:《一起撸个DL框架》 GitHub获取源码:https://github.com/flying-forever/OurDL blibli视频合集:https://space.bilibili.com/3493285974772098/channel/series 上一篇:【一起撸个DL框架】2 节点与计算图的搭建 在上一节中,我们定义了加法节点和变量节点类,搭建

    2024年02月02日
    浏览(49)
  • 【一起撸个DL框架】4 反向传播求梯度

    CSDN个人主页:清风莫追 欢迎关注本专栏:《一起撸个DL框架》 GitHub获取源码:https://github.com/flying-forever/OurDL blibli视频合集:https://space.bilibili.com/3493285974772098/channel/series 上一篇:【一起撸个DL框架】3 前向传播 前面我们已经介绍了前向传播,而本节即将介绍的 反向传播 中的

    2024年02月01日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包