引入依赖
<!-- 引入 Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.4.RELEASE</version> </dependency>
创建 Spring 的配置文件
Spring 的配置文件可以放在项目的任意位置,没有硬性要求,文件名称也没有要求,但是官方建议叫做:applicationContext.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- id:创建 Bean 的名字,要求唯一 --> <!-- name:创建 Bean 别名 --> <!-- class:创建 Bean 的全限定名 --> <bean name="USER,u1,u2" class="world.xuewei.User"/> <bean id="stu" name="student" class="world.xuewei.Student"/> </beans>
- id 属性:创建 Bean 的名字,要求唯一。如果这个 Bean 只需要使用一次,那么可以省略配置 id 属性,Spring 会默认分配一个名字,格式为:class属性 + ‘#数字’,数字表示在工厂中相同类型 Bean 的编码,从 0 开始,例如:
world.xuewei.User#0
,如果没有指定 id,但是指定了 name,那么会将 name(如果是多个 name,那么会取第一个 name)赋予给 id 属性 - name 属性:创建 Bean 的别名,如果没有指定 name,但是指定了 id,那么会将 id 赋予 name 属性。name 可以同时指定多个,用英文逗号分隔即可:
- class 属性:创建 Bean 的全限定名
Spring 核心 API ApplicationContext
Spring 的 ApplicationContext 是 Spring 框架中的一个关键接口,用于管理和提供应用程序的配置信息和 Bean 实例。它是 Spring IoC(控制反转)容器的实现之一,负责加载、配置和初始化 Bean,并提供对它们的访问。
ApplicationContext 提供了以下主要功能:
- Bean 实例化和管理:ApplicationContext 负责根据配置信息实例化和管理应用程序中的 Bean。它会解析 Bean 的定义,创建 Bean 对象,并在需要时将其注入到其他 Bean 中。
- 依赖注入(Dependency Injection):ApplicationContext 实现了依赖注入,即自动将依赖关系通过配置或注解方式注入到对象中。这样可以降低组件之间的耦合度,并提高代码的可维护性和可测试性。
- 生命周期管理:ApplicationContext 能够管理 Bean 的生命周期。它在 Bean 实例化之后,可以调用特定的回调方法来执行初始化操作,并在应用程序关闭时销毁 Bean 实例。
- 配置元数据的加载和解析:ApplicationContext 负责加载并解析配置文件或配置类中的元数据信息。这些元数据包含了 Bean 的定义、依赖关系、切面配置等信息。
- AOP 支持:ApplicationContext 提供了对面向切面编程(AOP)的支持。它可以自动为 Bean 应用切面,并将切面逻辑织入到目标对象中。
Spring 的 ApplicationContext 主要有两个主要实现:
- ClassPathXmlApplicationContext:从类路径下的 XML 配置文件加载和初始化应用程序上下文。它会在类路径下搜索并解析 XML 文件,将其中定义的 Bean 实例化并添加到容器中。
- AnnotationConfigApplicationContext:基于 Java 注解的配置方式加载和初始化应用程序上下文。它可以扫描指定的包或类,并根据注解配置来创建和管理 Bean。
这两个实现都是 ApplicationContext 接口的具体实现类,提供了不同的配置方式和灵活性,适用于不同的应用场景。
ApplicationContext 是一种重量级资源,需要在启动时加载和初始化大量的 Bean,可能带来一定的性能开销。然而,它同时也是线程安全的,可以在多线程环境中安全地使用。开发者在使用 ApplicationContext 时需要注意处理 Bean 的线程安全性问题。
常用方法测试
package world.xuewei; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.Arrays; /** * @author 薛伟 * @since 2023/9/14 20:51 */ public class MainTest { private ApplicationContext context; @Before public void before() { // 指定配置文件,创建 Spring 工厂 context = new ClassPathXmlApplicationContext("/applicationContext.xml"); } /** * 通过 Spring 的工厂获得对象 */ @Test public void testGetBean() { // 通过 Bean 的 id/name 获取对象 User user = (User) context.getBean("user"); // 通过 Bean 的 id/name 获取对象,同时指定 Bean 的类型,省略强转的步骤 User user1 = context.getBean("USER", User.class); // 通过 Bean 的类型获取对象,注意在 Spring 的工厂中只能有唯一一个此类型的 Bean,否则会抛出异常:NoUniqueBeanDefinitionException User user2 = context.getBean(User.class); System.out.println(user); System.out.println(user1); System.out.println(user2); } /** * 获取工厂中 Bean 的名字 */ @Test public void testGetBeanNames() { // 返回工厂中所有 Bean 的 id String[] beanDefinitionNames = context.getBeanDefinitionNames(); Arrays.stream(beanDefinitionNames).forEach(System.out::println); // 返回工厂中指定类型 Bean 的 id String[] beanNamesForType = context.getBeanNamesForType(User.class); Arrays.stream(beanNamesForType).forEach(System.out::println); // 判断工厂中是否存在指定 id 的 Bean的定义(只能判断 id,不能判定 name) boolean containsBeanDefinition = context.containsBeanDefinition("user"); // 判断工厂中是否存在指定 id 的 Bean(既能判断 id,也能判定 name) boolean containsBean = context.containsBean("user"); } }
Spring 工厂的简单分析:
- 首先会根据
ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
来读取指定配置文件。- 读取配置文件就会得到所有要管理的 Bean 的定义(id、name、class…)
- 通过反射创建对象
Class.forName("world.xuewei.User")
- 默认调用的是对象的无参构造方法,即使将构造方法定义为私有,反射的方式也可以调用!