Skip to content

Spring Framework

简介

Spring Framework 是一个非侵入式、轻量级的 Java 开发框架,以控制反转(IoC)面向切面编程(AOP)为核心。它的目标是简化企业级 Java 应用开发,通过提供一套统一、高效、可测试的编程模型,帮助开发者构建高质量的应用。

Spring 采用模块化设计,你可以按需引入所需模块,无需引入全部依赖。主要模块包括:

  • 核心功能(Core Container):提供 IoC 容器(BeanFactory、ApplicationContext)和依赖注入功能,是整个框架的基础。
  • AOP 与 Aspects:提供 AOP 实现(基于代理)以及与 AspectJ 的集成。
  • 数据访问与集成:简化 JDBC、ORM(Hibernate、JPA、MyBatis)、事务管理(声明式事务)等。
  • Web 模块:提供 Spring MVC 框架,支持构建 Web 应用和 RESTful API。
  • 测试模块:对 JUnit、TestNG 的集成支持,方便进行单元测试和集成测试。
  • 其他模块:如消息(JMS)、邮件、调度(Task)、远程调用等。

控制反转(Ioc)与依赖注入(DI)

控制反转将对象的创建和对象之间的依赖关系的管理从程序代码中转移到外部容器(即 Spring Ioc 容器)。 依赖注入:容器在运行期动态地将某种依赖关系注入到对象中。常见的注入方式包括构造器注入Setter注入字段注入

  • 传统方式:对象自己创建依赖的对象(new 出来),导致代码高度耦合,难以测试和维护。
  • Spring 方式:对象的创建和依赖关系交给 Spring 容器管理。只需要定义依赖关系(例如通过构造器、Setter 或 字段),容器在运行时自动将所需依赖注入进来。这就是依赖注入,而控制反转则是指控制权从对象自身转移到了容器。

面向切面编程(AOP)

Spring Ioc 容器

简介

Spring Ioc 容器是整个 Spring 框架的核心,它负责管理对象的生命周期和依赖关系,实现控制反转和依赖注入。

Ioc 容器是一个具有一来注入能力的对象工厂,它负责:

  • 创建对象:根据配置(XML、注解 或 Java 配置)实例化 Java 对象(称为 Bean)。
  • 管理依赖:解析 Bean 之间的依赖关系,并在运行时将依赖注入到响应 Bean 中。
  • 管理生命周期:控制 Bean 的作用域(单例、原型等)以及初始化、销毁等回调。
  • 提供扩展点:允许开发者在容器处理 Bean 的不同阶段插入自定义逻辑。

容器的两大核心接口

Ioc容器有两大核心接口。BeanFactory 是 Spring Ioc 容器的最基础、最核心的接口。它定义了获取和管理 Bean 所需的基本方法。ApplicationContextBeanFactory 的子接口,它不仅继承了 BeanFactory 的所有功能,还扩展并增强了其能力,是实际开中最常用、最推荐使用的接口。

特性BeanFactoryApplicationContext
定位基础的、轻量级的工厂接口高级的、功能丰富的应用上下文
加载时机延迟加载 (按需创建)预加载 (启动时创建)
功能丰富度只有基本的 Bean 管理功能包含事件、国际化、资源访问、AOP、Profile 等高级功能
是否推荐使用一般不直接使用,作为底层实现强烈推荐,绝大多数场景下使用
典型应用场景极简的、对启动性能要求极高的嵌入式/移动应用企业级应用、Web 应用、微服务等

BeanFactory

  • 顶级接口:定义了 Ioc 容器的基本功能,如getBean()containsBean()isSingleton()等。
  • 延迟加载:只有在调用getBean()时才实例化 Bean,适合资源受限的环境。
  • 典型实现DefaultListableBeanFactory,通常不直接使用,而是作为 ApplicationContext 的内部基础。

ApplicationContext

  • BeanFactory的子接口:继承了 BeanFactory 的所有功能,并增加了企业级特性:
    • 国际化支持(MessageSource)
    • 时间发布与监听(ApplicationEventPublisher)
    • 资源访问(ResourceLoader)
    • 自动注册 BeanPostProcessor、BeanFactoryPostProcessor
    • Web 应用支持(WebApplicationContext)
  • 预加载单例:容器启动后立即实例化所有单例 Bean(可通过 lazy-init 覆盖)。
  • 常用实现类
    • ClassPathXmlApplicationContext:从类路径加载 XML 配置文件。
    • FileSystemXmlApplicationContext:从文件系统加载 XML 配置文件。
    • AnnotationConfigApplicationContext:基于注解 或 Java 配置类创建容器。
    • WebApplicationCOntext:专为 Web 应用设计,如 AnnotationConfigWebApplicationContext。

BeanDefinition

BeanDefinition作为Bean的元数据载体,封装了Bean的所有配置信息(如类名、作用域、初始化方法、属性值等),相当于一个蓝图,告诉Spring如何创建和管理这个Bean。

属性名描述作用
beanClass指定bean类的全限定名用于通过读取指定路径下的类文件
beanClass指定bean的类型用于通过反射创建bean实例
scope定义bean的作用域
singleton, prototype
request, session等
决定bean是单例还是每次请求都创建新实例
lazyInit标识是否延迟初始化控制bean是否应该延迟初始化
factoryBeanName如果使用工厂方法创建bean,则指定工厂bean的名字配合factoryMethodName使用来指定创建bean的工厂bean
factoryMethodName如果使用工厂方法创建bean,则指定工厂方法的名字配合factoryBeanName使用来指定创建bean的方法
propertyValues包含所有设置到bean上的属性值用于注入依赖或设置bean的属性值
constructorArgumentValues包含传递给bean构造函数的所有参数值用于指定构造函数注入时需要的参数
initMethodName指定bean初始化后要调用的方法名在bean的所有属性设置完成后调用,进行一些初始化操作
destroyMethodName指定bean销毁前要调用的方法名在容器关闭时调用,进行资源清理等操作
role定义bean的角色
ROLE_APPLICATION
ROLE_SUPPORT
ROLE_INFRASTRUCTURE
表示bean的角色,有助于理解其用途
description对bean定义的描述提供关于bean定义的额外信息,便于理解和维护
java
public abstract class AbstractBeanDefinition 
   extends BeanMetadataAttributeAccessor
   implements BeanDefinition, Cloneable {
     
     // volatile关键字用于声明一个变量,确保其值的修改对所有线程都是立即可见的
     @Nullable
	 private volatile Object beanClass;
	 
}
java
     /**
	 * Specify the bean class name of this bean definition.
	 */
	@Override
	public void setBeanClassName(@Nullable String beanClassName) {
		this.beanClass = beanClassName;
	}
java
    /**
	 * Specify the class for this bean.
	 * @see #setBeanClassName(String)
	 */
	public void setBeanClass(@Nullable Class<?> beanClass) {
		this.beanClass = beanClass;
	}
java
     /**
	 * Return the current bean class name of this bean definition.
	 */
	@Override
	@Nullable
	public String getBeanClassName() {
		Object beanClassObject = this.beanClass;
		if (beanClassObject instanceof Class) {
			return ((Class<?>) beanClassObject).getName();
		}
		else {
			return (String) beanClassObject;
		}
	}
java
	/**
	* Return the specified class of the bean definition (assuming it is resolved already).
	**/
    public Class<?> getBeanClass() throws IllegalStateException {
		Object beanClassObject = this.beanClass;
		if (beanClassObject == null) {
			throw new IllegalStateException("No bean class specified on bean definition");
		}
		if (!(beanClassObject instanceof Class)) {
			throw new IllegalStateException(
					"Bean class name [" + beanClassObject + "] has not been resolved into an actual Class");
		}
		return (Class<?>) beanClassObject;
	}

BeanDefinition的beanClass属性

BeanDefinition的beanClass属性为Object类型

beanClass起初存储的是一个字符串值,值为目标bean类的全限定名(Fully Qualified Name)。

一旦beanClass被设置为某个具体的Class<?>对象,它允许Spring容器直接使用反射来创建该类型的实例,而不需要再经过类名到Class对象的转换过程。

@startuml

' 定义接口和抽象类 interface BeanDefinition {

  • 定义Bean的元数据 }

interface AnnotatedBeanDefinition {

  • 获取注解元数据 }

abstract class AbstractBeanDefinition {

  • 通用属性和默认实现 }

' 具体实现类 class GenericBeanDefinition {

  • 通用配置,支持动态父定义 }

class ScannedGenericBeanDefinition {

  • 组件扫描生成的Bean定义 }

class AnnotatedGenericBeanDefinition {

  • 注解直接定义的Bean(如@Component) }

class RootBeanDefinition {

  • 合并后的最终Bean定义 }

class ConfigurationClassBeanDefinition {

  • 基于@Bean方法的定义 }

class ClassDerivedBeanDefinition {

  • 专为类派生场景设计 }

' 已过时的旧类 class ChildBeanDefinition {

  • 已过时(旧版继承父Bean定义) }

' 继承和实现关系 BeanDefinition <|.. AbstractBeanDefinition BeanDefinition <|.. AnnotatedBeanDefinition

AbstractBeanDefinition <|-- RootBeanDefinition AbstractBeanDefinition <|-- GenericBeanDefinition AbstractBeanDefinition <|-- ChildBeanDefinition

RootBeanDefinition <|-- ConfigurationClassBeanDefinition RootBeanDefinition <|-- ClassDerivedBeanDefinition GenericBeanDefinition <|-- ScannedGenericBeanDefinition GenericBeanDefinition <|-- AnnotatedGenericBeanDefinition

' 接口实现关系 AnnotatedBeanDefinition <|.. ScannedGenericBeanDefinition AnnotatedBeanDefinition <|.. AnnotatedGenericBeanDefinition AnnotatedBeanDefinition <|.. ConfigurationClassBeanDefinition

' 注解说明 note top of ChildBeanDefinition: Deprecated (Spring 2.5+ 后不再推荐使用)

@enduml

类名特点使用场景
RootBeanDefinition继承自AbstractBeanDefinition,用于描述最基础和完整的bean定义信息。不依赖于父bean定义。适用于需要明确指定bean所有属性值的情况,特别是在XML配置或编程式注册bean定义时。
ConfigurationClassBeanDefinition继承自RootBeanDefinition,主要用于处理基于@Configuration类的bean定义,支持嵌套配置类等高级特性。当使用@Configuration注解进行Java配置时自动使用,简化了基于配置类的bean管理。
ClassDerivedBeanDefinition继承自RootBeanDefinition,主要用于从工厂方法创建的bean定义,帮助推断实际类型。在需要通过工厂方法动态创建bean,并且需要类型推断的情况下使用。
ChildBeanDefinition继承自AbstractBeanDefinition,允许一个bean继承另一个bean的定义,可以覆盖某些特定的属性。当多个bean共享一些共同的配置但又需要在某些方面有所区别时非常有用。
GenericBeanDefinition继承自AbstractBeanDefinition,提供了一种通用的bean定义方式,可以动态设置或修改各种bean属性,如作用域、初始化方法等。适用于几乎所有场景,尤其是那些需要在运行时根据条件动态调整bean配置的情况。
ScannedGenericBeanDefinition继承自GenericBeanDefinition,专门用于组件扫描过程中发现的bean定义,提供了对扫描到的注解元数据的支持。在使用组件扫描(例如@ComponentScan)自动检测候选组件时使用,便于自动注册和管理组件。
AnnotatedGenericBeanDefinition继承自GenericBeanDefinition,特别设计用来处理带有注解的类,支持注解元数据访问。在基于注解的配置场景下使用,特别是当需要编程式地注册带注解的bean定义时。

在Spring中,我们经常会通过以下几种方式来定义Bean:

  1. <bean/>标签
  2. @Bean注解
  3. @Component(@Service,@Controller)注解

这些,我们可以称之申明式定义Bean。

我们还可以编程式定义Bean,那就是直接通过BeanDefinition注册Bean的元配置信息,比如:

java
public class ServeApplication {
	public static void main(String[] args) {

		// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

		// 在容器中注册BeanDefinition
		// 使用BeanDefinitionBuilder构建BeanDefinition,使用的是 GenericBeanDefinition 类
		AbstractBeanDefinition beanDefinitionOfOrderService = BeanDefinitionBuilder.genericBeanDefinition(OrderService.class)
				.setScope(BeanDefinition.SCOPE_SINGLETON) // 设置作用域为 单例
				.setInitMethodName("test") // 设置初始化方法
				.setLazyInit(false) // 设置非懒加载, 默认也是非懒加载
				.getBeanDefinition();

		applicationContext.registerBeanDefinition("orderService", beanDefinitionOfOrderService);
		applicationContext.refresh();
		
		OrderService orderService = applicationContext.getBean(OrderService.class);
		System.out.println(orderService);
		orderService.test();

	}
	
}
java
public class Test {

	public static void main(String[] args) {

		// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

		// 在容器中注册BeanDefinition
		// 直接 new AnnotatedGenericBeanDefinition,解读UserService.class
		AnnotatedGenericBeanDefinition annotatedGenericBeanDefinitionOfUserService = new AnnotatedGenericBeanDefinition(UserService.class);
		// 如果UserService类中未添加@Component等配置元信息,需要自行定义,否则在getBean时无法获取 NoSuchBeanDefinition
		// annotatedGenericBeanDefinitionOfUserService.setBeanClass(UserService.class);
		// annotatedGenericBeanDefinitionOfUserService.setInitMethodName("test");
		// annotatedGenericBeanDefinitionOfUserService.setLazyInit(true);
		applicationContext.registerBeanDefinition("userService", annotatedGenericBeanDefinitionOfUserService);

		UserService userService = applicationContext.getBean(UserService.class);
		System.out.println(userService);

		userService.test();

	}
	
}
java
/**
* 此时的OrderService可以不添加@Component的注解配置信息,  
* 因为已经在BeanDefinition中定义了Bean的配置元信息
**/
public class OrderService {

	public void test() {
		System.out.println("orderService");
	}

}
java
/**
* 此时的UserService仍然需要添加@Component,  
* 因为只是在AnnotatedGenericBeanDefinition的构造方法中传入了UserService.class,  
* 构造方法内部还是会解读UserService.class文件内容,获取对应Bean的配置元信息,  
* 并解析为AnnotatedGenericBeanDefinition对象存储起来
**/
@Component
public class UserService {

	public void test(){
		System.out.println("userService");
	}
	
}

和编程式事务类似,通过,@Bean,@Component等申明式方式所定义的Bean,最终都会被Spring解析为对应的BeanDefinition对象,并放入Spring容器中。

RootBeanDefinition

直接实现 BeanDefinition 接口,不依赖于父 Bean 定义。适用于定义独立的、完整的 Bean 配置。 当需要明确指定一个 Bean 的所有属性值时使用,特别是在 XML 配置或编程式注册 Bean 定义时。

ConfigurationClassBeanDefinition

ConfigurationClassBeanDefinition 主要用于处理基于 @Configuration 注解的类的 Bean 定义。这些配置类通常包含用 @Bean 注解的方法,这些方法定义了如何创建和配置 Spring 容器中的 Beans。

ClassDerivedBeanDefinition

ClassDerivedBeanDefinition 是 Spring 中的一个内部类,主要用于从工厂方法创建的 Bean 定义过程中帮助推断实际返回对象的类型。它继承自 AbstractBeanDefinition 并实现了 BeanDefinition 接口。

GenericBeanDefinition

自 Spring 2.5 引入以来,逐渐成为最常用的 Bean 定义方式,因为它提供了极大的灵活性。 支持动态更改 Bean 的各种属性,如作用域、自动装配模式等。 由于其灵活性和通用性,它被广泛应用于基于注解的配置、Java 配置以及其他需要程序化定义 Bean 的场景中。

ScannedGenericBeanDefinition

基于注解的配置支持:ScannedGenericBeanDefinition 特别适合于处理那些通过注解(如 @Component, @Service, @Repository, @Controller 等)标注的类。
这些类在被扫描后,会根据它们的注解和类信息生成对应的 ScannedGenericBeanDefinition 实例。

java
package cn.knowledge;

import cn.knowledge.service.UserService;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ServeApplication {

	public static void main(String[] args) {

		// 扫描, 创建非懒加载的单例Bean 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		/**
		 * 打印
		 * Generic bean:
		 * 	class [cn.knowledge.service.UserService];
		 * 	scope=singleton;
		 * 	abstract=false;
		 * 	lazyInit=null;
		 * 	autowireMode=0;
		 * 	dependencyCheck=0;
		 * 	autowireCandidate=true;
		 * 	primary=false;
		 * 	factoryBeanName=null;
		 * 	factoryMethodName=null;
		 * 	initMethodName=null;
		 * 	destroyMethodName=null;
		 */
		BeanDefinition userServiceBeanDefinition = applicationContext.getBeanDefinition("userService");
		System.out.println(userServiceBeanDefinition);

		/**
		 * 打印 class org.springframework.context.annotation.ScannedGenericBeanDefinition
		 */
		Class<? extends BeanDefinition> beanDefinitionClass = userServiceBeanDefinition.getClass();
		System.out.println(beanDefinitionClass);

		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.test();

	}
}
java
@ComponentScan("cn.knowledge")
public class AppConfig {

}
java
@Component
public class UserService {

	public void test(){
		System.out.println("userService");
	}

}

AnnotatedGenericBeanDefinition

支持注解元数据:使得可以通过注解@Component, @Service, @Repository, @Controller 等注解来定义bean,并能够访问这些注解相关的元数据信息
通过扫描注解定义的Bean时,最终会被解析为ScannedGenericBeanDefinition类来存储Bean的元信息。
也可以在容器中直接使用AnnotatedGenericBeanDefinition类来解读注解定义的Bean,最终会被解析为AnnotatedGenericBeanDefinition类来存储Bean的元信息。

java
package cn.knowledge;

import cn.knowledge.service.UserService;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ServeApplication {

	public static void main(String[] args) {

		// 扫描, 创建非懒加载的单例Bean 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

        // 直接向 ApplicationContext 中注册注解定义的Bean对象,生成 AnnotatedGenericBeanDefination
		AnnotatedGenericBeanDefinition annotatedGenericBeanDefinitionOfUserService = new AnnotatedGenericBeanDefinition(UserService.class);
		applicationContext.registerBeanDefinition("userService", annotatedGenericBeanDefinitionOfUserService);
		applicationContext.refresh();

		/**
		 * 打印
		 * Generic bean: class [cn.knowledge.service.UserService]; 
		 * scope=; 
		 * abstract=false; 
		 * lazyInit=null; 
		 * autowireMode=0; 
		 * dependencyCheck=0; 
		 * autowireCandidate=true; 
		 * primary=false; 
		 * factoryBeanName=null; 
		 * factoryMethodName=null; 
		 * initMethodName=null; 
		 * destroyMethodName=null
		 */
		userServiceOfBeanDefinition = applicationContext.getBeanDefinition("userService");
		System.out.println(userServiceOfBeanDefinition);

		/**
		 * 打印 class org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition
		 */
		beanDefinitionClassOfUserService = userServiceOfBeanDefinition.getClass();
		System.out.println(beanDefinitionClassOfUserService);

		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.test();

	}
}
java
package cn.knowledge.service;

@Component
public class UserService {

	public void test(){
		System.out.println("userService");
	}

}

ChildBeanDefinition

BeanDefinitionReader

BeanDefinitionReader接口设计的初衷主要为了从特定资源(如XML文件、Groovy脚本等)读取bean定义的方法,其核心方法是loadBeanDefinitions,用于从特定资源加载和注册bean定义。

AnnotatedBeanDefinitionReader

然而,AnnotatedBeanDefinitionReader 类设计的目的是支持基于注解的bean定义注册过程,它提供了更便捷的方法来手动注册带有特定注解的类,如@Component, @Service, @Repository, @Controller等类,而不是从外部资源读取配置信息,它的职责与典型的BeanDefinitionReader实现(例如XmlBeanDefinitionReader或GroovyBeanDefinitionReader)有所不同,可以直接把某个类的配置信息解析并转换为BeanDefinition,
因此,AnnotatedBeanDefinitionReader 类并未实现BeanDefinitionReader接口 比如

java
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);

// 将User.class解析为BeanDefinition
annotatedBeanDefinitionReader.register(User.class);

System.out.println(context.getBean("user"));

WARNING

注意:它能解析的注解是:@Conditional,@Scope、@Lazy、@Primary、@DependsOn、@Role、@Description

XmlBeanDefinitionReader

可以解析标签

java
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);
int i = xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");

System.out.println(context.getBean("user"));

ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner是扫描器,但是它的作用和BeanDefinitionReader类似, 它可以进行扫描,扫描某个包路径,对扫描到的类进行解析, 比如,扫描到的类上如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition, 比如:

java
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.refresh();

ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
scanner.scan("com.zhouyu");

System.out.println(context.getBean("userService"));

BeanDefinitionRegistry

BeanFactory

BeanFactory 是 Spring IoC 容器的灵魂——它本质是一个延迟加载的、可配置的、能管理对象生命周期和依赖关系的高级工厂,定义了整个 Spring 容器最基本的功能规范。其核心思想是将对象的创建权和依赖关系管理权从应用程序代码中剥离,交由外部容器统一管理。其作用是负责实例化、配置、组装和管理应用程序中的所有 Bean。

BeanFactory 可以想象成一个“超级智能的制造工厂”。只需要告诉它:“创建一个 UserService”,它就会根据预先设定的“生产图纸”(配置),自动把 UserService 及其依赖的 UserDao 等部件组装好并交付。

延迟加载

BeanFactory 并不会在容器启动时就立即创建所有的 Bean。只有当应用程序第一次调用getBean()方法时,BeanFactory 才会去检查、创建并装配该 Bean。

BeanFactory 是一个 “按需生产” 的工厂,只在你需要的时候才开始工作。

DefaultListableBeanFactory

ApplicationContext

ApplicationContext 继承了 ListableBeanFactory 和 HierarchicalBeanFactory,而 ListableBeanFactory 和 HierarchicalBeanFactory 都继承自 BeanFactory,所以可以认为 ApplicationContext 继承了 BeanFactory,是 BeanFactory 的一种,拥有 BeanFactory 支持的所有功能,不过 ApplicationContext 比 BeanFactory 更加强大

ApplicationContext 接口在 Spring 源码中的定义
java
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

            ...
}
接口名称核心作用与功能描述关键特性典型应用场景
EnvironmentCapable提供对应用运行时环境的抽象访问能力。允许读取和管理配置属性(如 PropertySource)、激活不同的 Profile(如 dev, prod)等。✅ 支持多环境配置(如 @Profile("dev")
✅ 统一访问 application.properties / application.yml 等配置文件
✅ 可动态切换环境(如 spring.profiles.active=prod
1. 配置不同环境的数据库连接。
2. 条件化加载 Bean(@ConditionalOnProperty)。
3. 动态切换日志级别或功能开关。
ListableBeanFactory扩展了 BeanFactory,提供了获取所有已注册 Bean 的元信息的能力。✅ 支持 getBeanNamesForType(Class<T>):按类型查找所有符合条件的 Bean 名称。
✅ 支持 getBeanDefinitionNames():获取所有 Bean 定义的名称列表。
✅ 支持 containsBeanDefinition(String name):检查是否存在某个 Bean 定义。
1. 实现自动装配逻辑(如 @Autowired 依赖查找)。
2. 检查某类是否已被注册为 Bean。
3. 在 AOP 切面中分析目标类的 Bean 信息。
HierarchicalBeanFactory支持父子容器结构,即一个容器可以拥有一个父容器,实现“继承”机制。当在当前容器找不到指定的 Bean 时,会自动向父容器查询。✅ 支持容器层次结构(getParentBeanFactory())。
✅ 父容器的配置可被子容器“继承”。
✅ 常用于模块化开发或 Web 应用中的上下文分层。
1. Spring MVC 中 WebApplicationContextRoot WebApplicationContext 之间的父子关系。
2. 多模块项目中,共享公共配置的子容器。
MessageSource提供国际化(i18n)消息解析功能。允许应用程序根据用户的语言和地区偏好,动态加载对应的本地化消息。✅ 支持 getMessage(String code, Object[] args, Locale locale):按代码和区域获取消息。
✅ 支持 ResourceBundleMessageSource 等实现。
✅ 可以从 messages.propertiesmessages_zh.properties 等文件中读取。
1. 多语言网站或 App(如中文、英文界面切换)。
2. 错误提示、提示语的多语言支持。
ApplicationEventPublisher提供事件发布与监听机制。允许组件之间通过事件进行松耦合通信。✅ 支持 publishEvent(Object event):发布事件。
✅ 支持 @EventListener 注解自动注册监听器。
✅ 事件可异步处理(配合 @Async)。
1. 用户注册后发送欢迎邮件(UserRegisteredEvent)。
2. 订单创建后触发库存扣减(OrderCreatedEvent)。
3. 系统状态变更通知其他服务。
ResourcePatternResolver提供统一的资源定位与模式匹配能力。可以方便地从各种来源(文件系统、类路径、URL)加载资源,并支持通配符(如 classpath*:config/*.xml)。✅ 支持 getResource(String location):获取单个资源。
✅ 支持 getResources(String locationPattern):根据模式匹配获取多个资源。
✅ 支持 classpath*:file:http: 等前缀。
1. 加载多个 XML 配置文件(classpath*:beans/*.xml)。
2. 读取静态资源(图片、模板文件)。
3. 批量处理配置文件或脚本。

AnnotationConfigApplicationContext

AnnotationConfigApplicationContext继承实现结构

  1. ConfigurableApplicationContext
    • 继承了ApplicationContext接口,增加了
    • 添加事件监听器、
    • 添加BeanFactoryPostProcessor、
    • 设置Environment,
    • 获取ConfigurableListableBeanFactory等功能
  2. AbstractApplicationContext
    • 实现了ConfigurableApplicationContext接口
  3. GenericApplicationContext
    • 继承了AbstractApplicationContext,拥有了所有ApplicationContext的功能
    • 实现了BeanDefinitionRegistry接口,可以注册BeanDefinition
    • 类中有一个属性 DefaultListableBeanFactory beanFactory
  4. AnnotationConfigRegistry
    • 可以单独注册某个为类为BeanDefinition(可以处理该类上的@Configuration注解,已经可以处理@Bean注解),同时可以扫描
  5. AnnotationConfigApplicationContext
    • 继承了GenericApplicationContext
    • 实现了AnnotationConfigRegistry接口

ClassPathXmlApplicationContext

ClassPathXmlApplicationContext继承实现结构 它也是继承了AbstractApplicationContext,但是相对于AnnotationConfigApplicationContext而言,功能没有AnnotationConfigApplicationContext强大,比如不能注册BeanDefinition

国际化

java
@Bean
public MessageSource messageSource() {
	ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
	messageSource.setBasename("messages");
	return messageSource;
}

有了这个Bean,你可以在你任意想要进行国际化的地方使用该MessageSource。 同时,因为ApplicationContext也拥有国家化的功能,所以可以直接这么用:

java
context.getMessage("test", null, new Locale("en_CN"))

资源加载

ApplicationContext还拥有资源加载的功能,比如,可以直接利用ApplicationContext获取某个文件的内容:

java
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

Resource resource = context.getResource("file://D:\\IdeaProjects\\spring-framework-5.3.10\\tuling\\src\\main\\java\\com\\zhouyu\\service\\UserService.java");
System.out.println(resource.contentLength());

你可以想想,如果你不使用ApplicationContext,而是自己来实现这个功能,就比较费时间了。

还比如你可以:

java
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

Resource resource = context.getResource("file://D:\\IdeaProjects\\spring-framework-5.3.10\\tuling\\src\\main\\java\\com\\zhouyu\\service\\UserService.java");
System.out.println(resource.contentLength());
System.out.println(resource.getFilename());

Resource resource1 = context.getResource("https://www.baidu.com");
System.out.println(resource1.contentLength());
System.out.println(resource1.getURL());

Resource resource2 = context.getResource("classpath:spring.xml");
System.out.println(resource2.contentLength());
System.out.println(resource2.getURL());

获取运行时环境

java
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

Map<String, Object> systemEnvironment = context.getEnvironment().getSystemEnvironment();
System.out.println(systemEnvironment);

System.out.println("=======");

Map<String, Object> systemProperties = context.getEnvironment().getSystemProperties();
System.out.println(systemProperties);

System.out.println("=======");

MutablePropertySources propertySources = context.getEnvironment().getPropertySources();
System.out.println(propertySources);

System.out.println("=======");

System.out.println(context.getEnvironment().getProperty("NO_PROXY"));
System.out.println(context.getEnvironment().getProperty("sun.jnu.encoding"));
System.out.println(context.getEnvironment().getProperty("zhouyu"));

注意,可以利用

java
@PropertySource("classpath:spring.properties")

来使得某个properties文件中的参数添加到运行时环境中

事件发布

先定义一个事件监听器

java
@Bean
public ApplicationListener applicationListener() {
	return new ApplicationListener() {
		@Override
		public void onApplicationEvent(ApplicationEvent event) {
			System.out.println("接收到了一个事件");
		}
	};
}

然后发布一个事件:

java
context.publishEvent("kkk");

类型转化

在Spring源码中,有可能需要把String转成其他类型,所以在Spring源码中提供了一些技术来更方便的做对象的类型转化,关于类型转化的应用场景, 后续看源码的过程中会遇到很多。

PropertyEditor

这其实是JDK中提供的类型转化工具类

java
public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {

	@Override
	public void setAsText(String text) throws IllegalArgumentException {
		User user = new User();
		user.setName(text);
		this.setValue(user);
	}
}
java
StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
propertyEditor.setAsText("1");
User value = (User) propertyEditor.getValue();
System.out.println(value);

如何向Spring中注册PropertyEditor:

java
@Bean
public CustomEditorConfigurer customEditorConfigurer() {
	CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
	Map<Class<?>, Class<? extends PropertyEditor>> propertyEditorMap = new HashMap<>();
    
    // 表示StringToUserPropertyEditor可以将String转化成User类型,在Spring源码中,如果发现当前对象是String,而需要的类型是User,就会使用该PropertyEditor来做类型转化
	propertyEditorMap.put(User.class, StringToUserPropertyEditor.class);
	customEditorConfigurer.setCustomEditors(propertyEditorMap);
	return customEditorConfigurer;
}

假设现在有如下Bean:

java
@Component
public class UserService {

	@Value("xxx")
	private User user;

	public void test() {
		System.out.println(user);
	}

}

那么test属性就能正常的完成属性赋值

ConversionService

Spring中提供的类型转化服务,它比PropertyEditor更强大

java
public class StringToUserConverter implements ConditionalGenericConverter {

	@Override
	public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
		return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);
	}

	@Override
	public Set<ConvertiblePair> getConvertibleTypes() {
		return Collections.singleton(new ConvertiblePair(String.class, User.class));
	}

	@Override
	public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
		User user = new User();
		user.setName((String)source);
		return user;
	}
}
java
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new StringToUserConverter());
User value = conversionService.convert("1", User.class);
System.out.println(value);

如何向Spring中注册ConversionService:

java
@Bean
public ConversionServiceFactoryBean conversionService() {
	ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
	conversionServiceFactoryBean.setConverters(Collections.singleton(new StringToUserConverter()));

	return conversionServiceFactoryBean;
}

TypeConverter

整合了PropertyEditor和ConversionService的功能,是Spring内部用的

java
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.registerCustomEditor(User.class, new StringToUserPropertyEditor());
//typeConverter.setConversionService(conversionService);
User value = typeConverter.convertIfNecessary("1", User.class);
System.out.println(value);

OrderComparator

OrderComparator是Spring所提供的一种比较器,可以用来根据@Order注解或实现Ordered接口来执行值进行笔记,从而可以进行排序。

java
public class A implements Ordered {

	@Override
	public int getOrder() {
		return 3;
	}

	@Override
	public String toString() {
		return this.getClass().getSimpleName();
	}
}
java
public class B implements Ordered {

	@Override
	public int getOrder() {
		return 2;
	}

	@Override
	public String toString() {
		return this.getClass().getSimpleName();
	}
}
java
public class Main {

	public static void main(String[] args) {
		A a = new A(); // order=3
		B b = new B(); // order=2

		OrderComparator comparator = new OrderComparator();
		System.out.println(comparator.compare(a, b));  // 1

		List list = new ArrayList<>();
		list.add(a);
		list.add(b);

		// 按order值升序排序
		list.sort(comparator);

		System.out.println(list);  // B,A
	}
}

另外,Spring中还提供了一个OrderComparator的子类:AnnotationAwareOrderComparator,它支持用@Order来指定order值。比如:

java
@Order(3)
public class A {

	@Override
	public String toString() {
		return this.getClass().getSimpleName();
	}

}
java
@Order(2)
public class B {

	@Override
	public String toString() {
		return this.getClass().getSimpleName();
	}

}
java
public class Main {

	public static void main(String[] args) {
		A a = new A(); // order=3
		B b = new B(); // order=2

		AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator();
		System.out.println(comparator.compare(a, b)); // 1

		List list = new ArrayList<>();
		list.add(a);
		list.add(b);

		// 按order值升序排序
		list.sort(comparator);

		System.out.println(list); // B,A
	}
}

BeanPostProcessor

BeanPostProcess表示Bena的后置处理器,我们可以定义一个或多个BeanPostProcessor,比如通过一下代码定义一个BeanPostProcessor:

java
@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("初始化前");
		}

		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("初始化后");
		}

		return bean;
	}
}

一个BeanPostProcessor可以在任意一个Bean的初始化之前以及初始化之后去额外的做一些用户自定义的逻辑,当然,我们可以通过判断beanName来进行针对性处理(针对某个Bean,或某部分Bean)。

我们可以通过定义BeanPostProcessor来干涉Spring创建Bean的过程。

BeanFactoryPostProcessor

BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似,BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程。比如,我们可以这样定义一个BeanFactoryPostProcessor:

java
@Component
public class ZhouyuBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("加工beanFactory");
	}
}

我们可以在postProcessBeanFactory()方法中对BeanFactory进行加工。

FactoryBean

上面提到,我们可以通过BeanPostPorcessor来干涉Spring创建Bean的过程,但是如果我们想一个Bean完完全全由我们来创造,也是可以的,比如通过FactoryBean:

java
@Component
public class ZhouyuFactoryBean implements FactoryBean {

	@Override
	public Object getObject() throws Exception {
		UserService userService = new UserService();

		return userService;
	}

	@Override
	public Class<?> getObjectType() {
		return UserService.class;
	}
}

通过上面这段代码,我们自己创造了一个UserService对象,并且它将成为Bean。但是通过这种方式创造出来的UserService的Bean,只会经过初始化后,其他Spring的生命周期步骤是不会经过的,比如依赖注入。

有同学可能会想到,通过@Bean也可以自己生成一个对象作为Bean,那么和FactoryBean的区别是什么呢?其实在很多场景下他俩是可以替换的,但是站在原理层面来说的,区别很明显,@Bean定义的Bean是会经过完整的Bean生命周期的。

ExcludeFilter和IncludeFilter

这两个Filter是Spring扫描过程中用来过滤的。ExcludeFilter表示排除过滤器,IncludeFilter表示包含过滤器。

比如以下配置,表示扫描com.zhouyu这个包下面的所有类,但是排除UserService类,也就是就算它上面有@Component注解也不会成为Bean。

java
@ComponentScan(value = "com.zhouyu",
excludeFilters = {@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = UserService.class)}.)
public class AppConfig {
}

再比如以下配置,就算UserService类上没有@Component注解,它也会被扫描成为一个Bean。

java
@ComponentScan(value = "com.zhouyu",
includeFilters = {@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = UserService.class)})
public class AppConfig {
}

FilterType分为:

  1. ANNOTATION:表示是否包含某个注解
  2. ASSIGNABLE_TYPE:表示是否是某个类
  3. ASPECTJ:表示否是符合某个Aspectj表达式
  4. REGEX:表示是否符合某个正则表达式
  5. CUSTOM:自定义

在Spring的扫描逻辑中,默认会添加一个AnnotationTypeFilter给includeFilters,表示默认情况下Spring扫描过程中会认为类上有@Component注解的就是Bean。

MetadataReader、ClassMetadata、AnnotationMetadata

在Spring中需要去解析类的信息,比如类名、类中的方法、类上的注解,这些都可以称之为类的元数据,所以Spring中对类的元数据做了抽象,并提供了一些工具类。

MetadataReader表示类的元数据读取器,默认实现类为SimpleMetadataReader。比如:

java
public class Test {

	public static void main(String[] args) throws IOException {
		SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();
		
        // 构造一个MetadataReader
        MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.zhouyu.service.UserService");
		
        // 得到一个ClassMetadata,并获取了类名
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
	
        System.out.println(classMetadata.getClassName());
        
        // 获取一个AnnotationMetadata,并获取类上的注解信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		for (String annotationType : annotationMetadata.getAnnotationTypes()) {
			System.out.println(annotationType);
		}

	}
}

需要注意的是,SimpleMetadataReader去解析类时,使用的ASM技术。

为什么要使用ASM技术,Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的类是非常多的,那如果在Spring启动时就把这些类全部加载进JVM了,这样不太好,所以使用了ASM技术。