自学内容网 自学内容网

【Spring】Bean的作用域和Spring的执行流程

目录

1.Bean的作用域

1.1 Singleton(单例)

1.2 Prototype(原型)

1.3 适用于SpringMVC的作用域

2.Spring的执行流程

2.1 Spring容器的初始化

2.2 Bean的创建和装配

2.3 Bean的生命周期管理

2.4 其他重要概念

3. Spring的执行流程简洁版


1.Bean的作用域

Spring Bean的作用域定义了Bean的生命周期和可见性。Spring 支持多种作用域,以下为各个作用域的讲解。


1.1 Singleton(单例)

Singleton,是一个默认模式也是一种单例模式。

  • 在整个Spring IoC容器中,Spring只会创建该Bean的一个实例。
  • 所有的请求和对象都共享这个单例Bean

创建一个 SpecializedCourse 类,以该类来演示存储 Bean 和使用 Bean 的流程。

@Component
public class SpecializedCourse {
    private int id;
    private String name;
    private String content;

    @Override
    public String toString() {
        return "SpecializedCourse{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", content='" + content + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

在公共类中设置 SpecializedCourses 的原始数据为 id=1name=Javacontent=数据类型

@Component
public class SpecializedCourses {
    @Bean("specializedCourse")
    public SpecializedCourse getSpecializedCourse() {
        //原始信息
        SpecializedCourse specializedCourse = new SpecializedCourse();
        specializedCourse.setId(1);
        specializedCourse.setName("Java");
        specializedCourse.setContent("数据类型");
        return specializedCourse;
    }
}

CourseService 类使用 SpecializedCourse 类中原始信息并修改为 id=2,name=C++,content=数据结构

@Service
public class CourseService {
    @Autowired
    private SpecializedCourse specializedCourse;

    public void getSpecializedCourse() {
        //原来的内容
        System.out.println(specializedCourse.toString());
        specializedCourse.setId(2);
        specializedCourse.setName("C++");
        specializedCourse.setContent("数据结构");
        //修改后的内容
        System.out.println(specializedCourse.toString());;
    }
}

CourseService2 类使用 SpecializedCourse 类中原始信息发现获取得是 CourseService 修改后的内容。

@Service
public class CourseService2 {
    @Autowired
    private SpecializedCourse specializedCourse;

    // 想要获取到原来的内容,发现已经被修改了
    public void getSpecializedCourse() {
        System.out.println(specializedCourse.toString());;
    }
}

 在 App 启动类中,对比 CourseService 和 CourseService2 使用 SpecializedCourse 后的结果。

public class App {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("Spring-config.xml");
        // CourseService
        CourseService courseService =
                context.getBean("courseService",CourseService.class);
        courseService.getSpecializedCourse();
        //CourseService2
        CourseService2 courseService2 =
                context.getBean("courseService2",CourseService2.class);
        courseService2.getSpecializedCourse();
    }
}

运行结果: 


1.2 Prototype(原型)

Prototype 英译为原型,在 Spring 框架中,当一个 Bean 的作用域被设置为“prototype”时,每次对该 Bean 的请求都会导致 Spring 容器创建一个新的 Bean 实例。这与单例(Singleton)作用域不同,后者在整个 Spring IoC 容器中只创建一个 Bean 实例。因此:

  • 每次请求都会创建一个新的Bean实例。
  • 适用于有状态的Bean。

因此,我们只需要将上述的 SpecializedCourses 原型数据加上 Scope 注解,就能实现原始数据不会被修改问题(实际上就是将该 Bean 对象设置为多例形式)。

@Component
public class SpecializedCourses {
    @Scope("prototype")
    @Bean("specializedCourse")
    public SpecializedCourse getSpecializedCourse() {
        SpecializedCourse specializedCourse = new SpecializedCourse();
        specializedCourse.setId(1);
        specializedCourse.setName("Java");
        specializedCourse.setContent("数据类型");
        return specializedCourse;
    }
}

App 启动类运行结果为:

Scope 注解两种写法

  1. @Scope("prototype")
  2. @Scope("ConfigurableBeanFactory.SCOPE_PROTOTYPE") 

1.3 适用于SpringMVC的作用域

适用于 Spring MVC 的作用域有三种:request、session、application

RequestScope

  • 描述:每个HTTP请求都会创建一个新的作用域,该作用域中的对象仅在当前请求的处理期间可见。请求完成后,作用域中的对象会被销毁。
  • 适用场景:适用于需要在请求级别上保持状态或处理特定请求的逻辑,如存储请求相关的数据。

SessionScope

  • 描述:在用户会话期间保持对象的可见性。当用户登录时创建会话作用域对象,直到用户注销或会话超时才销毁。
  • 适用场景:适用于需要在会话级别上保持状态或处理特定会话的逻辑,如存储用户信息或会话状态。

ApplicationScope

  • 描述:对象在整个应用程序中都是可见的,且生命周期最长。对象在应用程序启动时创建,直到应用程序关闭才销毁。
  • 适用场景:适用于需要在应用程序级别上保持状态或处理全局逻辑的对象,如存储全局配置或共享数据。

2.Spring的执行流程

Spring的执行流程是一个复杂但有序的过程,它主要涉及Spring容器的初始化和Bean的创建、装配及生命周期管理。以下是Spring执行流程的详细解析:

2.1 Spring容器的初始化

  1. 读取配置信息

    Spring在启动时首先会读取应用程序提供的Bean配置信息,这些信息通常定义在XML配置文件或注解中。
  2. 生成Bean配置注册表

    根据读取的配置信息,Spring容器会生成一份相应的Bean配置注册表,该注册表包含了所有需要实例化的Bean及其依赖关系。
  3. 实例化BeanFactory

    对于ApplicationContext容器,它内部封装了一个BeanFactory对象来实现对容器的操作。BeanFactory是Spring IoC容器的基础,它封装了Bean的信息,并提供了创建和管理Bean的接口。
  4. 解析配置文件

    使用XmlBeanDefinitionReader等解析器解析配置文件,将Bean定义(BeanDefinition)注册到容器中。

2.2 Bean的创建和装配

  1. 实例化Bean

    当客户向容器请求一个尚未初始化的Bean时,或初始化Bean时需要注入另一个尚未初始化的依赖时,容器会调用createBean进行实例化。对于ApplicationContext容器,它会在容器启动结束后实例化所有的Bean。
  2. 依赖注入

    在Bean实例化后,Spring会根据BeanDefinition中的信息进行依赖注入。这通常通过构造函数注入、Setter方法注入或接口注入等方式实现。
  3. Aware接口注入

    Spring会检测Bean是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean。这允许Bean获取到Spring容器的相关资源和服务。
  4. BeanPostProcessor前置处理

    在Bean正式构造完成前,Spring会调用实现了BeanPostProcessor接口的类的前置处理方法(postProcessBeforeInitialization),允许对Bean进行额外的处理或修改。
  5. 初始化Bean

    接下来,Spring会调用Bean的初始化方法。这可以通过实现InitializingBean接口并定义afterPropertiesSet方法来实现,也可以通过在配置文件中指定init-method属性来实现。
  6. BeanPostProcessor后置处理

    在Bean初始化完成后,Spring会调用实现了BeanPostProcessor接口的类的后置处理方法(postProcessAfterInitialization),允许对Bean进行进一步的修改或处理。

2.3 Bean的生命周期管理

  1. 使用Bean

    经过上述步骤后,Bean已经准备好被应用程序使用。应用程序可以通过调用Bean的方法来执行相应的业务逻辑。
  2. 销毁Bean

    当容器关闭或Bean不再需要时,Spring会调用Bean的销毁方法。这可以通过实现DisposableBean接口并定义destroy方法来实现,也可以通过在配置文件中指定destroy-method属性来实现。

2.4 其他重要概念

  1. 控制反转(IoC)

    IoC是Spring的核心思想之一,它通过将组件的控制权从组件本身转移到外部容器来管理和解耦组件之间的依赖关系。
  2. 依赖注入(DI)

    DI是IoC的一种实现方式,它通过在创建组件时将所需的依赖对象注入到组件中来实现组件之间的解耦。
  3. 面向切面编程(AOP)

    AOP是Spring的另一个重要特性,它通过将横切关注点(如日志、事务管理等)从主要业务逻辑中分离出来并模块化地封装为切面,从而在需要的地方将这些横切关注点织入到应用程序中。

综上所述,Spring的执行流程是一个涉及容器初始化、Bean创建和装配以及生命周期管理的复杂过程。通过这个过程,Spring能够高效地管理和维护应用程序中的对象及其依赖关系。


3. Spring的执行流程简洁版

1.定义配置文件

定义 Spring 的.xml 配置文件,通常名为 spring-config.xml 放置在 resource 文件底下。

2.读取配置文件

读取 spring-config.xml 文件,获取 .xml 文件所设置的 Bean 对象地址(包名等等),为下次获取到 Bean 对象做准备。

3.实例化Bean对象

通过 <Bean></Bean> 标签(xml配置文件)、类注解(@Controller、@Service...)、方法注解来实例化 Bean 对象。

4.依赖注入

通过构造方法、Setter方法、@Autowired注解、@Resource注解,来获取 Bean 对象。在此就不举例子,可看本专栏内博文了解。

5.Bean就绪

此时就可以通过一些获取 Spring 的上下文的类从 Spring 容器中拿 Bean 对象(使用Bean对象)了,如 ApplicationContext 类中的 getBean 方法。

6.处理请求(用于SpringMVC)

如果 .xml 文件中有对于外部的请求,如别人想通过网络来获取你的 Bean 对象,此时就会使用到接受请求和处理请求即 RequestScope、SessionScope、ApplicationScope等。


本篇博客到这里就结束,感谢您的阅读!


原文地址:https://blog.csdn.net/weixin_64916311/article/details/143718507

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!