一、Spring源码-ApplicationContext

news2024/12/27 11:31:14

Spring源码篇-ApplicationContext

一、ApplicationContext

  ApplicationContext到底是什么?字面含义是应用的上下文。这块我们需要看看ApplicationContext的具体的结构。

image.png

  通过ApplicationContext实现的相关接口来分析,ApplicationContext接口在具备BeanFactory的功能的基础上还扩展了 应用事件发布,资源加载,环境参数国际化的能力。然后我们来看看ApplicationContext接口的实现类的情况。

image.png

  在ApplicationContext的实现类中有两个比较重要的分支 AbstractRefreshableApplicationContextGenericApplicationContext.

image.png

二、BeanFactory

  上面分析了 ApplicationContext接口的结构。然后我们来看看 BeanFactory在ApplicationContext中具体的实现是怎么样的

image.png

image.png

可以看到具体的实现是 DefaultListableBeanFactory .然后我们来看看他的体系结构

image.png

BeanFactory的继承体系

image.png

三、BeanDefinition

  然后我们来了解下ApplicationContext是如何来加载Bean定义的。具体代码我们需要分为XML配置文件和基于注解的两种方式来看。

1.基于XML方式

  我们先定义对应的application.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

	<bean id="beanE" class="com.study.spring.sample.config.BeanE" />

	<bean id="beanF" class="com.study.spring.sample.config.BeanF" ></bean>

	<context:annotation-config/>

	<context:component-scan base-package="com.study.spring.sample.config" ></context:component-scan>

</beans>

然后我们的测试类代码

public class XMLConfigMain {

	public static void main(String[] args) {
		ApplicationContext context = new GenericXmlApplicationContext(
				"classpath:com/study/spring/sample/config/application.xml");
		BeanF bf = context.getBean(BeanF.class);
		bf.do1();
	}
}

处理的过程 解析XML --> BeanDefinition --> BeanDefinitionRegistry --> BeanFactory

image.png

2.基于注解方式

  然后来看看基于注解方式的使用的情况。首先是我们的配置类

@Configuration
@ComponentScan("com.study.spring.sample.config")
public class JavaBasedMain {

	@Bean
	public BeanH getBeanH() {
		return new BeanH();
	}

	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(JavaBasedMain.class);

		BeanH bh = context.getBean(BeanH.class);
		bh.doH();
	}
}

然后是我们的测试类

public class AnnotationMain {

	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext("com.study.spring.sample.config");

		BeanG bg = context.getBean(BeanG.class);
		bg.dog();
	}
}

注解使用有两种方法:

  1. 配置扫描路径
  2. 配置@Configuration的注解类

2.1 this构造方法

  在this的构造方法中会完成相关的配置处理。

	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

首先是AnnotatedBeanDefinitionReader(this)方法。会完成核心的ConfigurationClassPostProcessor的注入。ConfigurationClassPostProcessor 会完成@Configuration相关的注解的解析

image.png

this.scanner其实就是创建了一个对应的扫描器

image.png

2.2 扫描实现

  扫描就需要进入到scan方法中。

image.png

image.png

image.png

完成相关的注册

image.png

2.3 @Configuration

  @Configuration的解析其实是在refresh方法中来实现的。

image.png

3.小结

  通过上面的分析其实我们已经对Bean定义的扫描,解析和注册过程有了一定的了解。归纳为:

  1. reader解析XML,完成xml方法配置的bean定义
  2. scanner扫描指定包下的类,找出带有@Component注解的类,注册成Bean定义
  3. 通过ConfigurationClassPostProcessor对带有@Configuration注解的类进行处理,解析它上面的注解,以及类中带有@Bean 注解,加入这些的Bean的定义。

4.BeanDefinition

  ;然后我们来看看BeanDefinition的继承结构

image.png

  继承属性访问器和元数据接口,增加了Bean定义操作,实现了数据和操作解耦。属性访问器和元数据接口接着往下看。

4.1 BeanMetadataElement

  BeanMetadataElement提供了获取数据源的方式,也就是可以指导Bean是来自哪个类。

public interface BeanMetadataElement {

	/**
	 * Return the configuration source {@code Object} for this metadata element
	 * (may be {@code null}).
	 */
	@Nullable
	default Object getSource() {
		return null;
	}

}

4.2 BeanMetadataAttribute元数据属性

  实现了元数据接口,增加了属性的名字和值。。


public class BeanMetadataAttribute implements BeanMetadataElement {

	private final String name;

	@Nullable
	private final Object value;

	@Nullable
	private Object source;

}

4.3 AttributeAccessor属性访问器

  AttributeAccessor用来给Bean定义了增删改查属性的功能

public interface AttributeAccessor {

	/**
	 * Set the attribute defined by {@code name} to the supplied {@code value}.
	 * If {@code value} is {@code null}, the attribute is {@link #removeAttribute removed}.
	 * <p>In general, users should take care to prevent overlaps with other
	 * metadata attributes by using fully-qualified names, perhaps using
	 * class or package names as prefix.
	 * @param name the unique attribute key
	 * @param value the attribute value to be attached
	 */
	void setAttribute(String name, @Nullable Object value);

	/**
	 * Get the value of the attribute identified by {@code name}.
	 * Return {@code null} if the attribute doesn't exist.
	 * @param name the unique attribute key
	 * @return the current value of the attribute, if any
	 */
	@Nullable
	Object getAttribute(String name);

	/**
	 * Remove the attribute identified by {@code name} and return its value.
	 * Return {@code null} if no attribute under {@code name} is found.
	 * @param name the unique attribute key
	 * @return the last value of the attribute, if any
	 */
	@Nullable
	Object removeAttribute(String name);

	/**
	 * Return {@code true} if the attribute identified by {@code name} exists.
	 * Otherwise return {@code false}.
	 * @param name the unique attribute key
	 */
	boolean hasAttribute(String name);

	/**
	 * Return the names of all attributes.
	 */
	String[] attributeNames();

}

4.4 AttributeAccessorSupport属性访问抽象实现类

  内部定义了1个map来存放属性。

public abstract class AttributeAccessorSupport implements AttributeAccessor, Serializable {

	/** Map with String keys and Object values. */
	private final Map<String, Object> attributes = new LinkedHashMap<>();


	@Override
	public void setAttribute(String name, @Nullable Object value) {
		Assert.notNull(name, "Name must not be null");
		if (value != null) {
			this.attributes.put(name, value);
		}
		else {
			removeAttribute(name);
		}
	}
    //  ......
}

4.5 BeanMetadataAttributeAccessor元数据属性访问器

  继承AttributeAccessorSupport具备属性访问功能,实现BeanMetadataElement具备获取元数据功能。 **AbstractBeanDefinition就继承于它,使得同时具有属性访问和元数据访问的功能 **。

image.png

结合AbstractBeanDefinition.来看看他们的类图结构

image.png

5. BeanDefinition继承体系

5.1 AnnotatedBeanDefinition

  增加了2个方法,获取bean所在类的注解元数据和工厂方法元数据,这些数据在进行解析处理的时候需要用到。

public interface AnnotatedBeanDefinition extends BeanDefinition {

	/**
	 * Obtain the annotation metadata (as well as basic class metadata)
	 * for this bean definition's bean class.
	 * @return the annotation metadata object (never {@code null})
	 */
	AnnotationMetadata getMetadata();

	/**
	 * Obtain metadata for this bean definition's factory method, if any.
	 * @return the factory method metadata, or {@code null} if none
	 * @since 4.1.1
	 */
	@Nullable
	MethodMetadata getFactoryMethodMetadata();

}

  该注解有三个具体的实现。ScannedGenericBeanDefinition、AnnotatedGenericBeanDefinition、ConfigurationClassBeanDefinition。

image.png

5.2 AbstractBeanDefinition模板类

  AbstractBeanDefinition我们可以称之为BeanDefinition的模板类。结构我们上面其实有梳理

image.png

  通过上面我们可以看到AbstractBeanDefinition 具备了 Bean元数据的获取和属性相关的操作。同时AbstractBeanDefinition的继承结构

image.png

5.3 RootBeanDefinition根bean定义

  它主要用在spring内部的bean定义、把不同类型的bean定义合并成RootBeanDefinition(getMergedLocalBeanDefinition方法)。没有实现BeanDefinition接口的设置获取父bean定义方法,不支持设置父子beanDefinition。

5.4 ConfigurationClassBeanDefinition

  用作ConfigurationClassPostProcessor解析过程中封装配置类的bean定义。

5.5 GenericBeanDefinition

  GenericBeanDefinition通用Bean的定义。

5.6 ScannedGenericBeanDefinition

  @ComponentScan扫描的bean定义使用。

5.7 AnnotatedGenericBeanDefinition

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/799149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【正规方程对波士顿房价数据集进行预测】

数据准备 我们首先需要加载波士顿房价数据集。该数据集包含房屋特征信息和对应的房价标签。 import pandas as pd import numpy as npdata_url "http://lib.stat.cmu.edu/datasets/boston" raw_df pd.read_csv(data_url, sep"\s", skiprows22, headerN…

初代AIGC明星独角兽,停摆在大模型元年

唏嘘&#xff01;AIGC方兴未艾&#xff0c;但国内AIGC领域的昔日龙头独角兽&#xff0c;正站在风雨飘摇的悬崖边。 影谱科技&#xff0c;初代目AIGC明星公司&#xff0c;被爆已经面临经营不善、运营停摆的窘境。 这家成立于2009年的AI影像公司&#xff0c;一直专注大文娱产业…

JAVA线上问题排查降龙十八掌

现场问题一般有以下几种问题 CPU,磁盘&#xff0c;内存&#xff0c;GC问题&#xff0c;网络 同时例如jstack、jmap等工具也是不囿于一个方面的问题的&#xff0c;基本上出问题就是df、free、top 三连&#xff0c;然后依次jstack、jmap伺候&#xff0c;具体问题具体分析即可。 …

Vue3解决:Mockjs 引入后并访问 404(Not Found) 的页面报错问题

1、问题描述&#xff1a; 其一、报错为&#xff1a; GET http://localhost:5173/list 404 (Not Found) ncaught (in promise) AxiosError {message: Request failed with status code 404, name: AxiosError, code: ERR_BAD_REQUEST, config: {…}, request: XMLHttpRequest,…

【C语言初阶】指针篇—上

目录 1. 指针是什么&#xff1f;2. 指针和指针类型2.1 指针-整数2.2 指针的解引用 3. 野指针3.1 野指针成因1. 指针未初始化2. 指针越界访问3. 指针指向的空间释放 3.2 如何规避野指针 1. 指针是什么&#xff1f; 指针是什么&#xff1f; 指针理解的2个要点&#xff1a; > 1…

DAY14_FilterListenerAjaxAxiosJsonfastjson综合案例-axios和html交互

目录 1 Filter1.1 Filter概述1.2 Filter快速入门1.2.1 开发步骤1.2.2 代码演示 1.3 Filter执行流程1.4 Filter拦截路径配置1.5 过滤器链1.5.1 概述1.5.2 代码演示1.5.3 问题 1.6 案例1.6.1 需求1.6.2 分析1.6.3 代码实现1.6.3.1 创建Filter1.6.3.2 编写逻辑代码1.6.3.3 测试并抛…

计算机组成原理问答7

外围设备 1. I/O设备 输入设备(鼠标、键盘)、输出设备(显示器、打印机)、外存设备(光盘、硬盘) 2. I/O接口 又称I/O控制器、设备控制器,负责协调主机与外部设备之间的数据传输。 I/O控制方式 3. 程序查询方式 中断 关中断作用:实现原子操作。屏蔽可屏蔽的中断。…

备战秋招 | 笔试强训16

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、下列一段 C 代码的输出结果是&#xff08;&#xff09; #include <iostream> class Base { public:int Bar(char x){return (int)(x);}virtual int Bar(int x){return (2 * x);} }; clas…

如何启用路由器dhcp?快解析如何内网穿透?

一、什么是DHCP&#xff1f; 动态主机设置协议&#xff08;DHCP&#xff09;是一种使网络管理员能够集中管理和自动分配 IP 网络地址的通信协议。在网络中&#xff0c;每个联网设备都需要分配独有的 IP 地址。并当有新计算机移到网络中的其它位置时&#xff0c;能自动收到新的…

【阅读笔记】一种暗通道优先的快速自动白平衡算法

解决问题: 自动白平衡算法中存在白色区域检测错误导致白平衡失效的问题,作者提出了一种基于暗通道优先的白平衡算法。 算法思想: 图像中白色区域或者高饱和度区域的光线透射率较低,根据以上特性利用暗通道法计算图像中白色区域。 算法概述: 作者使用何凯明提出的基于暗…

MLP-Mixer:面向视觉的全mlp架构

文章目录 MLP-Mixer: An all-MLP Architecture for Vision摘要本文方法代码实验结果 MLP-Mixer: An all-MLP Architecture for Vision 摘要 卷积神经网络(cnn)是计算机视觉的首选模型。 最近&#xff0c;基于注意力的网络&#xff0c;如VIT&#xff0c;也变得流行起来。在本文…

四种刷题模式的爱刷题无后端无数据库刷题应用网站H5源码

四种刷题模式的爱刷题无后端无数据库刷题应用网站H5源码。提供了简单轻量化的部署方式和详细的四种刷题模式教程。该应用使用JSON作为题库的存储方式&#xff0c;层次清晰、结构简单易懂。 配套的word模板和模板到JSON转换工具可供使用&#xff0c;方便将题库从word格式转换为…

Python显示循环代码的进度条

目录 1. tqdm库 2. alive_progress库 3. progressbar库 1. tqdm库 tqdm是一个快速&#xff0c;可扩展的Python进度条&#xff0c;可以在Python长循环中添加一个进度提示信息 import time from tqdm import trangefor i in trange(100):# do somethingtime.sleep(0.5) 2. a…

Mysql原理篇--第一章 1条语句的执行

Mysql原理系列篇 第一章 1条语句的执行 文章目录 Mysql原理系列篇 第一章 1条语句的执行前言&#xff1a;1 连接mysql 服务端:1.1 通信模型&#xff1a;1.2 通信连接数&#xff1a; 2 sql 语句的到达存储引擎的流程:3 数据从存储引擎返回的流程&#xff1a;4 Buffer_pool 脏页的…

【云原生】Docker容器资源限制(CPU/内存/磁盘)

目录 ​编辑 1.限制容器对内存的使用 2.限制容器对CPU的使用 3.block IO权重 4.实现容器的底层技术 1.cgroup 1.查看容器的ID 2.在文件中查找 2.namespace 1.Mount 2.UTS 3.IPC 4.PID 5.Network 6.User 1.限制容器对内存的使用 ⼀个 docker host 上会运⾏若⼲容…

【Linux下6818开发板(ARM)】SecureCRT串口和交叉编译工具(巨细版!)

(꒪ꇴ꒪ ),hello我是祐言博客主页&#xff1a;C语言基础,Linux基础,软件配置领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff01;送给读者的一句鸡汤&#x1f914;&#xff1a;集中起来的意志可以击穿顽石!作者水平很有限&#xff0c;如果发现错误&#x…

策略:一致性行动原则,力出一孔

策略&#xff1a;一致性行动的原则 策略有很多种解释 经常跟战略混淆 趣讲大白话&#xff1a;就是指导方针 【趣讲信息科技238期】 **************************** 教员的游击战“16字口诀”很经典 敌进我退&#xff0c;敌退我进&#xff0c; 敌疲我打&#xff0c;敌驻我扰 曾国…

小城市当程序员好不好?

在职业发展中&#xff0c;小城市和大城市都有各自的机会和挑战。在大城市&#xff0c;C#的应用比例可能相对较低&#xff0c;学习C可能有一定的难度&#xff0c;而学习Java最好有人指导。在小城市&#xff0c;机会相对较少&#xff0c;跳槽的选择也有限。然而&#xff0c;小城市…

想转嵌入式或工控上位机,哪个前途更光明?

上位机开发的需求目前很大&#xff0c;根据BOSS上的数据&#xff0c;C#和WPF的需求较多。作为WPF开发者&#xff0c;薪资水平可以有较大的变动&#xff0c;主要取决于经验&#xff0c;20,000到30,000元的薪资并不难达到。工作环境因工种而异&#xff0c;不可避免地需要进行现场…

消息队列 - 数据库操作

这里写自定义目录标题 前言数据表的插入删除操作关于实现接口类的几个注意实现实现封装创建DataBaseManager 类另一种获取Bean对象的方式 对数据库进行单元测试 前言 上一篇博客, 我们将消息队列的实体类创建完毕了, 并且还写了一些关于数据库的操作, 接下来我们继续进行关于数…