Spring 中的 BeanFactory 和 ApplicationContext 详解

文章目录

  • 一、BeanFactory
    • 1、BeanFactory 的作用
    • 2、BeanFactory的实现类
    • 3、BeanFactory的创建
    • 4、BeanFactory与ApplicationContext的关系
    • 5、BeanFactory的工作原理
  • 二、ApplicationContext
    • 1、ApplicationContext 的作用
    • 2、ApplicationContext 的实现类
    • 3、ApplicationContext 使用示例

Spring 中的 BeanFactory 是框架中的一个核心接口,作为 Spring 容器的基础设施,负责创建、配置和管理Bean实例,同时提供了对Bean生命周期的管理和控制。

一、BeanFactory

BeanFactory 是 Spring 框架中最基本的容器接口,定义了 Spring 容器的核心方法,用于管理 Bean 的生命周期和依赖注入。这些核心方法包括但不限于 Bean 的实例化、依赖注入、配置和管理等。通过BeanFactory,可以灵活地获取和操作Bean实例,而无需手动管理对象的创建和依赖关系。

1、BeanFactory 的作用

  • Bean 实例化:根据配置信息或注解定义,创建应用程序中需要的Bean实例。负责解析Bean定义,处理依赖关系,并将Bean实例化为可用的对象。
  • 依赖注入:将所需依赖注入到 Bean 中,确保 Bean 能正确运行。包括设置属性值、调用初始化方法等。
  • 配置和管理:根据配置文件或注解来配置和管理 Bean 实例,提供了各种方法来获取和操作 Bean 实例。
  • 生命周期管理:管理 Bean 的整个生命周期,包括创建、初始化、使用和销毁。

2、BeanFactory的实现类

Spring 提供了多个 BeanFactory 的实现类,以满足不同的需求。

  • XmlBeanFactory(已废弃):通过 XML 配置文件来创建和管理 Bean 的实例化、配置和管理的实现类。在Spring 3.1 版本后被废弃,建议使用 GenericXmlApplicationContextClassPathXmlApplicationContext 等更现代的容器实现。
  • DefaultListableBeanFactory:BeanFactory 的常用实现,提供了灵活的 Bean 注册、实例化和依赖注入机制。是许多Spring容器的基础实现。
  • XmlBeanDefinitionReader:这个类负责从 XML 文件中读取 Bean 定义并将其注册到 BeanFactory 中。
  • AnnotationConfigApplicationContext:这个类支持基于注解的配置和管理方式,提供了对 @Component@Service@Repository@Configuration 等注解的支持。

3、BeanFactory的创建

BeanFactory的创建方式主要包括XML配置方式、Java配置方式和注解配置方式:

  • XML 配置方式:这是创建 BeanFactory 的传统方式。需要在 XML 配置文件中定义 Bean 的信息,包括 Bean 的名称、类路径、属性等,通过加载配置文件来创建和管理 BeanFactory 。
  • Java配置方式:在 Java 类中定义 Bean 的创建和依赖关系,通过配置类来创建和管理 BeanFactory。通常涉及到使用 @Configuration 注解来标识配置类,并使用 @Bean 注解来定义 Bean 的实例化、配置和管理信息。
  • 注解配置方式:在 Java 类上添加相应的注解来标识该类是一个 Bean,并进行相应的配置信息。Spring 会自动扫描并创建相应的 Bean,并将其添加到 ApplicationContext 中,AnnotationConfigApplicationContext 作为其子类,同样支持注解配置方式。

4、BeanFactory与ApplicationContext的关系

BeanFactory是Spring框架中最基本的容器接口,但在实际开发中,ApplicationContext接口的使用更为广泛。ApplicationContext 是 BeanFactory 的子接口,提供了更多的功能,如国际化支持、事件传播、自动扫描组件等。因此,会使用ApplicationContext 来代替 BeanFactory。然而,理解BeanFactory仍然是理解Spring内部工作原理的基础。

5、BeanFactory的工作原理

BeanFactory 在存储和获取 Bean 时,主要通过使用数据结构(如Map)和反射机制来实现。在创建 BeanFactory 实例时,通常会使用一个容器(如HashMap)来存储Bean对象。这个容器可以将Bean的名称作为键,Bean对象作为值进行存储。当需要访问某个Bean时,可以通过名称快速地获取到对应的Bean对象。

  • 首先,当使用 Spring 的 XML 配置文件或注解定义Bean时,BeanFactory 会读取配置文件或扫描注解,并将 Bean 的相关信息解析成 BeanDefinition 对象(例如 Bean 的类名、属性、依赖关系等)。
  • 然后,BeanFactory 会将这些 BeanDefinition 对象存储在一个 Map 中,以 Bean 的名称作为键,BeanDefinition 对象作为值。
  • 当需要获取某个 Bean 时,BeanFactory 会根据 Bean 的名称从 Map 中查找对应的 BeanDefinition 对象,并根据 BeanDefinition 中的信息使用反射机制创建 Bean 的实例并返回给调用方。
  • 在创建 Bean 实例时,BeanFactory 还会处理 Bean 的依赖关系,确保所有相关的依赖都会被正确地解析和注入。

二、ApplicationContext

ApplicationContext 是 Spring 应用程序的核心,它不仅负责创建和管理Bean,还提供了多种企业级服务,如事件传播、国际化、资源加载等。是 Spring IoC 容器高级形态,提供了对 Bean 的全面管理以及对应用程序环境的支持。

1、ApplicationContext 的作用

  • Bean 的创建和管理:负责实例化和管理应用中的所有 Bean ,包括它们的创建、配置、生命周期管理等。提供了对 Bean 的访问和控制,使得 Bean 之间的依赖关系可以通过依赖注入的方式轻松实现。
  • 依赖注入:支持依赖注入,允许 Bean 轻松地获取其依赖的其他 Bean。
  • 国际化支持:根据不同的语言环境加载不同的资源文件实现多语言。通过继承 MessageSource 接口来支持消息解析和国际化。
  • 事件传播:可以发布事件,并允许其他组件注册监听器来处理这些事件,这种机制实现了组件之间的解耦。
  • 资源加载:提供了一个统一的接口,可以方便的加载和管理各种资源,如配置文件、XML 文件、Properties 文件等。
  • 面向切面编程:提供了对 AOP 的支持,允许通过配置切面来实现横切关注点的模块化。
  • 中央接口:为应用程序提供配置的中央接口,在应用程序运行时这是只读的,但如果实现支持这一点,则可以重新加载。
  • 继承性:后代上下文中的定义总是优先于父上下文中的定义,这意味着单个父上下文可以被整个 web 应用共享。

2、ApplicationContext 的实现类

  • ClassPathXmlApplicationContext:从类路径中获取上下文定义文件,适用于测试工具以及嵌入在 jar 中的应用程序上下文。
  • FileSystemXmlApplicationContext:从文件系统或 URL 获取上下文定义文件,适用于独立的应用程序。
  • AnnotationConfigApplicationContext:在 Spring 3.0 中引入,允许通过 Java 配置类来配置应用程序上下文,与 @Configuration@Component 等注解一起工作。

3、ApplicationContext 使用示例

以下代码示例,包括 MyBean 类的定义,该类具有一个 sayHello 方法。代码演示了如何使用 @Configuration@Bean 注解来配置 Spring 应用程序上下文,并通过 AnnotationConfigApplicationContext 来启动 Spring 容器。

1、MyBean.java



```java
public class MyBean {
    public void sayHello() {
        System.out.println("Hello, Spring!");
    }
}

2、AppConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}

3、Main.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        // 创建应用上下文
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        
        // 获取Bean并调用方法
        // 注意:这里使用了context.getBean(Class requiredType)方法,它会返回指定类型的单个Bean实例
        // 如果容器中有多个相同类型的Bean,则会抛出异常。在这个例子中,我们只有一个MyBean实例。
        MyBean myBean = context.getBean(MyBean.class);
        
        // 调用MyBean的sayHello方法
        myBean.sayHello();
        
        // (可选)关闭应用程序上下文,释放资源。在独立应用程序中,这通常不是必需的,
        // 因为JVM会在应用程序退出时自动回收资源。但在某些情况下(如Web应用程序),
        // 显式关闭上下文是一个好习惯。
        // context.close();
    }
}
  • MyBean 类定义了一个简单的 sayHello 方法,该方法打印一条消息。
  • AppConfig 类是一个配置类,使用 @Configuration 注解标记。包含一个 @Bean 注解的方法 myBean ,该方法返回一个新的 MyBean 实例。
  • Main 类是包含 main 方法的入口点。创建一个 AnnotationConfigApplicationContext 实例,将 AppConfig.class 传递给它以加载配置。它使用 context.getBean(MyBean.class) 获取 MyBean 的实例,并调用其 sayHello 方法。

4、运行 Main 类的 main 方法

Hello, Spring!

表明Spring容器已成功创建并管理了 MyBean 实例,并且已正确调用了其 sayHello 方法。

你可能感兴趣的:(Java,后端,spring,java,后端)