spring之bean的生命周期以及单例多例的区别

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: spring之bean的生命周期以及单例多例的区别

一、简介


( 1 ) 是什么

在Spring框架中,JavaBean的背景可以追溯到Java语言的发展和面向对象编程的原则。JavaBean作为一种特定的编程规范和约定,被引入到Spring框架中,以实现更加灵活和可扩展的开发方式。


在Spring框架中,JavaBean是一个普通的Java类,遵循一些特定的命名和属性规范。一个JavaBean类必须具备以下特征:

1. 私有的成员变量:JavaBean类中的属性通常是私有的,以保护数据,同时提供公共的getter和setter方法来访问和修改属性的值。

2. 无参构造方法:JavaByouean类必须提供一个无参构造方法,用于实例化该类的对象。

3. 可序列化:JavaBean类可以实现Serializable接口,以便在网络传输或持久化时能够将对象转换为字节流。这样,在分布式环境下,可以方便地传输JavaBean对象。

JavaBean在Spring框架中扮演了重要的角色,具有以下优点:

1. 封装数据:JavaBean通过私有属性和公共的getter和setter方法提供对数据的封装,遵循面向对象的封装原则,提高了程序的安全性和可维护性。

2. 兼容性:JavaBean对象可以与其他Spring组件无缝集成,如IoC容器、数据绑定、AOP等。通过JavaBean,可以将业务逻辑和数据操作解耦,增加了代码的灵活性和可扩展性。

3. 可重用性:JavaBean可以在不同的应用程序中被重复使用,无需重新编写逻辑。这种可重用性可以大大提高开发效率,减少代码冗余。

4. 数据绑定:Spring框架提供了数据绑定功能,可以通过JavaBean将请求参数直接绑定到对象的属性上,简化了数据处理的过程。

5. 持久化:JavaBean类可以通过持久化技术(如Hibernate、JPA等)将对象保存到数据库中,实现数据的持久化存储和检索。

综上所述,学习JavaBean对于使用Spring框架进行Java开发是非常重要的。它可以帮助我们实现代码的模块化、封装和重用,提高开发效率和代码质量,同时也符合面向对象的设计原则。


( 2 ) 背景概述

  • 面向对象编程:Java是一种面向对象的编程语言,强调通过封装、继承和多态等特性来建立可维护和可扩展的软件系统。JavaBean作为一种符合面向对象原则的编程风格,鼓励将数据和行为封装到独立的对象中。
  • 反射与可扩展性:Java的反射机制提供了运行时动态获取类和对象信息的能力,这为JavaBean的创建和操作提供了基础。通过反射,Spring框架可以在运行时实例化JavaBean并设置属性,从而实现解耦和可扩展的编程模型。
  • Inversion of Control(IoC):IoC是Spring框架的核心概念之一,它通过将对象的创建和依赖注入的控制权交给框架来实现松耦合。JavaBean的使用正是为了支持IoC,通过约定和配置,Spring框架可以自动地管理和协调JavaBean对象的创建和依赖注入。
  • 数据绑定和数据访问:Spring框架提供了强大的数据绑定和数据访问的功能,可以通过JavaBean来实现请求参数与对象属性的自动绑定,并将JavaBean与数据库或其他数据源连接起来。这样可以简化开发过程,提高代码的可读性和可维护性。
  • AOP支持:JavaBean作为Spring框架中的组件,可以非常方便地与AOP(面向切面编程)进行集成,实现横切关注点的解耦。通过对JavaBean对象的增强,可以实现事务管理、日志记录、安全验证等共享的横切功能。

综上所述,JavaBean在Spring框架中的背景是基于Java语言的面向对象编程原则,结合反射、IoC和AOP等技术的应用。JavaBean的引入使得Spring框架更加灵活、可扩展,并提供了一种符合规范的对象编程模型,用于简化开发过程和管理对象的生命周期。


( 3 ) 作用

  • 在Spring框架中,JavaBean是指符合特定规范的普通Java类,它起到了组件的角色。JavaBean在Spring中充当了以下重要的角色和作用:
  • 组件化:JavaBean作为Spring框架中的组件,可以被容器管理和维护。通过将JavaBean注册到Spring的IoC容器中,可以实现对其生命周期的控制,包括创建、初始化、销毁等。
  • 依赖注入(Dependency Injection):JavaBean通过依赖注入实现对象之间的松耦合关系。在Spring中,通过配置信息或注解,容器可以自动将依赖注入到JavaBean中,避免了硬编码和耦合的问题,提高了代码的可测试性和可维护性。
  • 数据绑定:JavaBean可以作为数据模型,通过与Spring框架提供的数据绑定功能,将请求参数直接绑定到JavaBean的属性上。这样可以非常方便地处理用户提交的表单数据、进行数据验证和类型转换等操作。
  • AOP支持:JavaBean可以和AOP无缝集成,通过为JavaBean添加切面,可以实现横切关注点的解耦。例如,在JavaBean的方法上添加事务管理切面,实现对事务的控制,而JavaBean无需关心具体的事务管理代码。
  • 序列化与持久化:JavaBean可以通过实现Serializable接口,使得它们的实例可以被序列化为字节流,从而实现网络传输和持久化存储。在Spring中,通过JavaBean的持久化技术(如Hibernate、JPA等),可以将JavaBean的状态保存到数据库中。
  • 配置管理:JavaBean可以通过Spring提供的配置机制(如XML配置、注解配置等),在应用程序启动时进行加载和初始化,Spring容器根据配置信息创建相应的JavaBean对象。这种方式使得应用程序的配置更加灵活和可管理。

总的来说,JavaBean在Spring框架中扮演了重要的角色,它不仅是一个普通的Java类,还具有组件化、依赖注入、数据绑定、AOP支持等功能。学习和使用JavaBean,可以帮助开发人员更好地理解和使用Spring框架,从而提高开发效率和代码质量。


二、生命周期

2.1 讲述

在Spring中,JavaBean的生命周期涉及到以下类和接口:

1. 实例化:在这个阶段,Spring使用反射机制创建JavaBean的实例。主要使用的类是Class类,该类提供了获取类的构造方法的方法。在配置文件中,可以使用<bean>标签来配置JavaBean的实例化方式,包括使用默认构造方法实例化、使用静态工厂方法实例化或使用实例工厂方法实例化。

2. 属性注入:在实例化完成后,Spring会将属性值注入到JavaBean中。这个阶段使用到的类有BeanWrapper、BeanDefinition和PropertyValues。BeanWrapper是一个用于包装JavaBean的类,它可以通过反射设置JavaBean的属性值。BeanDefinition是一个用于描述JavaBean的元数据的类,它包含了JavaBean的类名、属性值等信息。PropertyValues是一个用于保存JavaBean属性值的类,它可以通过键值对的方式保存属性值。在配置文件中,可以使用<property>标签或通过注解来配置JavaBean的属性注入方式。

3. 初始化:在属性注入完成后,Spring会调用JavaBean的初始化方法。这个阶段可以通过实现InitializingBean接口或在配置文件中指定初始化方法来实现。InitializingBean接口中有一个afterPropertiesSet()方法,可以在该方法中进行初始化操作。另外,还可以通过在配置文件中使用init-method属性来指定初始化方法。在初始化方法中,可以进行一些对象的初始化操作,如初始化连接池、加载配置文件等。

4. 使用:在初始化完成后,JavaBean可以被其他组件或对象使用了。这个阶段主要是调用JavaBean的方法进行业务逻辑处理。

5. 销毁:当Spring容器关闭时,会调用JavaBean的销毁方法进行资源的释放。这个阶段可以通过实现DisposableBean接口或在配置文件中指定销毁方法来实现。DisposableBean接口中有一个destroy()方法,可以在该方法中进行资源释放操作。另外,还可以通过在配置文件中使用destroy-method属性来指定销毁方法。在销毁方法中,可以进行一些资源的释放操作,如关闭连接、释放内存等。

需要注意的是,JavaBean的生命周期是由Spring容器管理的,所以只有在Spring容器中才会进行相应的生命周期操作。如果使用纯Java方式创建的对象,则不会经过Spring的生命周期管理。在配置文件中,可以使用XML配置方式或注解方式来描述JavaBean的生命周期。XML配置方式可以通过<bean>标签来配置JavaBean的属性值、初始化方法和销毁方法。注解方式可以通过在JavaBean类上使用相应的注解来描述初始化方法和销毁方法,如@PostConstruct和@PreDestroy注解。


2.2 相关内容

1) . BeanDefinitionReader

在Spring中,BeanDefinitionReader是用于读取并解析配置文件的类,它在JavaBean的生命周期中起着重要的作用。

  • 在JavaBean的生命周期中,BeanDefinitionReader主要用于实例化和属性注入阶段。它会读取配置文件中的<bean>标签,并解析其中的属性值、初始化方法和销毁方法等信息。通过解析配置文件,BeanDefinitionReader可以获取到JavaBean的类名、属性值、初始化方法和销毁方法等元数据。
  • 在实例化阶段,BeanDefinitionReader会根据配置文件中的信息使用反射机制创建JavaBean的实例。它会根据配置文件中的<bean>标签中的class属性获取到JavaBean的类名,并使用反射机制创建JavaBean的实例。
  • 在属性注入阶段,BeanDefinitionReader会根据配置文件中的<property>标签获取到JavaBean的属性值,并使用反射机制将属性值注入到JavaBean中。它会根据配置文件中的<property>标签中的name属性获取到属性名,然后根据name属性获取到对应的属性值,并使用反射机制将属性值注入到JavaBean中。
  • 除了实例化和属性注入阶段,BeanDefinitionReader还可以在其他阶段发挥作用。例如,在初始化阶段,BeanDefinitionReader可以读取配置文件中的init-method属性,并将其作为初始化方法进行调用。在销毁阶段,BeanDefinitionReader可以读取配置文件中的destroy-method属性,并将其作为销毁方法进行调用。

总之,BeanDefinitionReader在JavaBean的生命周期中起着解析和读取配置文件的作用,它能够获取到JavaBean的元数据,并根据配置文件中的信息进行实例化、属性注入、初始化和销毁等操作。


2) . BeanDefinition

BeanDefinition是Spring框架中的一个重要概念,它用于描述和定义一个Bean的信息。

具体来说,BeanDefinition的作用主要有以下几个方面:


1. 定义Bean的属性:BeanDefinition定义了一个Bean的属性,包括Bean的类名、作用域、是否懒加载、依赖关系等。通过BeanDefinition,可以对Bean的属性进行配置和管理。

2. 描述Bean的依赖关系:BeanDefinition描述了Bean与其他Bean之间的依赖关系。它可以指定Bean所依赖的其他Bean,以及依赖的方式(如通过构造函数注入、setter方法注入等)。通过BeanDefinition,可以实现Bean之间的依赖注入。

3. 定义Bean的初始化和销毁方法:BeanDefinition可以定义Bean的初始化方法和销毁方法。它可以指定Bean在实例化之后需要执行的初始化方法,以及在销毁之前需要执行的销毁方法。通过BeanDefinition,可以实现对Bean生命周期的管理。

4. 扩展Bean的功能:通过BeanDefinition,可以对Bean的定义进行扩展,实现自定义的功能。可以在BeanDefinition中添加AOP切面、事务管理等功能,从而实现对Bean的增强。

5. 灵活配置Bean的定义:BeanDefinition提供了灵活的配置方式,可以通过XML配置文件、注解或编程的方式来定义Bean。可以根据需要,选择合适的方式来配置Bean的定义。

总之,BeanDefinition是Spring框架中用于描述和定义Bean的信息的重要概念。它定义了Bean的属性、依赖关系、初始化和销毁方法等信息,可以实现对Bean的配置和管理。通过BeanDefinition,可以实现灵活的Bean配置和扩展,从而实现对Bean的定制化功能。


3) . BeanFactoryPostProcessor

BeanFactoryPostProcessor是Spring框架中的一个扩展接口,它可以在Spring容器实例化Bean之后,对Bean的定义进行修改或扩展。

具体来说,BeanFactoryPostProcessor的作用主要有以下几个方面:

1. 修改Bean的定义:通过实现BeanFactoryPostProcessor接口,可以在Spring容器实例化Bean之前,对Bean的定义进行修改。可以添加、删除或修改Bean的属性值、作用域、依赖关系等。这样可以在不修改源代码的情况下,对Bean的定义进行动态调整。

2. 扩展Bean的定义:通过实现BeanFactoryPostProcessor接口,可以在Spring容器实例化Bean之前,对Bean的定义进行扩展。可以添加新的Bean定义,或者通过修改Bean的定义来实现自定义的扩展功能。例如,可以在Bean的定义中添加AOP切面、事务管理等功能。

3. 配置Bean的属性值:通过实现BeanFactoryPostProcessor接口,可以在Spring容器实例化Bean之前,对Bean的属性值进行配置。可以根据需要,动态地设置Bean的属性值,从而实现更灵活的配置。

4. 解析和处理Bean的定义:BeanFactoryPostProcessor接口还可以用于解析和处理Bean的定义。可以根据需要,对Bean的定义进行解析和处理,以实现特定的逻辑。例如,可以根据Bean的定义生成其他相关的Bean定义,或者根据Bean的定义进行一些逻辑判断和处理。

需要注意的是,BeanFactoryPostProcessor是在Spring容器实例化Bean之后,对Bean的定义进行修改或扩展的。它与BeanPostProcessor接口的区别在于,BeanFactoryPostProcessor是在Bean的定义阶段进行操作,而BeanPostProcessor是在Bean的实例化和初始化阶段进行操作。因此,BeanFactoryPostProcessor可以对Bean的定义进行修改,而BeanPostProcessor只能对Bean的实例进行操作。


4) . BeanFactory

BeanFactory是Spring框架中的核心接口之一,它是用于管理和获取Bean实例的工厂。

具体来说,BeanFactory的作用主要有以下几个方面:

1. 实例化Bean:BeanFactory负责根据配置文件或注解等方式,实例化JavaBean。它会根据配置文件中的<bean>标签或注解中的配置信息,使用反射机制创建JavaBean的实例。通过BeanFactory,可以方便地创建和获取各种类型的Bean实例。

2. 管理Bean的生命周期:BeanFactory管理着Bean的生命周期。它会在需要时创建Bean的实例,并在不需要时销毁Bean的实例。通过BeanFactory,可以控制Bean的创建、初始化和销毁等过程,实现对Bean的灵活管理。

3. 注入依赖关系:BeanFactory负责将Bean之间的依赖关系注入到Bean实例中。它会根据配置文件中的<property>标签或注解中的依赖关系,将依赖的Bean注入到目标Bean中。通过BeanFactory,可以实现Bean之间的依赖注入,从而实现松耦合的设计。

4. 提供Bean的访问接口:BeanFactory提供了访问Bean的接口,可以方便地获取已经实例化的Bean。通过BeanFactory,可以根据Bean的名称或类型,获取到对应的Bean实例。这样可以方便地在应用程序中使用Bean,实现各种功能。

总之,BeanFactory是Spring框架中用于管理和获取Bean实例的核心接口。它负责实例化Bean、管理Bean的生命周期、注入依赖关系和提供Bean的访问接口等功能,是Spring框架中实现IoC(控制反转)和DI(依赖注入)的重要组成部分。


5) . Aware

Aware是Spring框架中的一组接口,用于在Bean实例化过程中向Bean注入特定的资源或回调接口。

具体来说,Aware接口主要有以下几个作用:

1. 提供对Spring容器的访问:通过实现ApplicationContextAware接口,Bean可以获取对Spring容器的引用。这样可以在Bean中直接访问Spring容器的各种功能,如获取其他Bean、获取环境变量等。

2. 提供对BeanFactory的访问:通过实现BeanFactoryAware接口,Bean可以获取对BeanFactory的引用。这样可以在Bean中直接访问BeanFactory的各种功能,如获取Bean的定义、获取Bean的属性等。

3. 提供对Bean的名称的访问:通过实现BeanNameAware接口,Bean可以获取自己在Spring容器中的名称。这样可以在Bean中获取自己的名称,做一些特定的处理。

4. 提供对资源的访问:通过实现ResourceLoaderAware接口,Bean可以获取对资源加载器的引用。这样可以在Bean中直接加载资源,如读取配置文件、访问文件等。

5. 提供对消息源的访问:通过实现MessageSourceAware接口,Bean可以获取对消息源的引用。这样可以在Bean中直接访问消息源,实现国际化和本地化的功能。

通过实现这些Aware接口,Bean可以获取到Spring容器的相关资源或回调接口,从而实现对这些资源的访问或使用。这样可以在Bean中更方便地实现一些特定的功能,提高系统的灵活性和可扩展性。


三、模式

3.1 概述

Spring是一个综合性的开发框,如果不进行配置,它默认是单例模式

但它也可以配置为多例模式。


单例模式

Spring使用单例模式的主要优点和好处包括:


1. 节省资源:单例模式可以确保在整个应用程序中只有一个实例存在,节省了系统资源的开销。每次请求都返回同一个实例,避免了重复创建对象的开销。

2. 提高性能:由于单例模式只创建一个实例,避免了频繁的创建和销毁对象的开销,从而提高了系统的性能。

3. 避免竞争条件:在多线程环境下,使用单例模式可以避免多个线程同时访问和修改对象的状态,从而避免了竞争条件和数据不一致的问题。

4. 统一管理和协调资源:单例模式可以统一管理和协调系统中的共享资源,确保资源的正确使用和释放,避免资源泄漏和浪费。

5. 提供全局访问点:单例模式可以提供一个全局的访问点,方便其他对象或模块通过该访问点来获取实例,简化了对象的使用和调用。

6. 简化配置和管理:在Spring框架中,将Bean定义为单例模式可以简化配置和管理,只需要在配置文件或注解中声明为单例即可,Spring容器负责创建和管理单例对象。

总的来说,Spring使用单例模式的优点包括节省资源、提高性能、避免竞争条件、统一管理和协调资源、提供全局访问点以及简化配置和管理。这些优点使得Spring在处理大规模应用和高并发环境下表现出色,并且提供了更好的可扩展性和可维护性。


在使用单例模式时,可能会存在以下两个缺点:


1. 状态共享和线程安全问题:由于单例模式只创建一个实例,多个线程共享该实例,可能会导致状态共享和线程安全问题。如果多个线程同时访问和修改单例对象的状态,可能会导致数据不一致的问题。为了解决这个问题,需要在代码中进行适当的同步控制,增加了开发和维护的复杂度。

2. 依赖关系和耦合度高:单例模式会导致对象之间的依赖关系和耦合度较高。由于单例对象在整个系统中都是可见的,其他对象可能会直接依赖于单例对象,导致对象之间的紧耦合。这样一来,当需要对单例对象进行修改或替换时,可能会涉及到多个对象的修改,增加了系统的维护成本和风险。

需要注意的是,这些缺点并不是单例模式本身的问题,而是在使用单例模式时可能会出现的问题。通过合理的设计和使用,可以减轻这些问题的影响。比如,可以通过尽量避免共享状态、合理控制同步访问、使用线程安全的方式创建单例对象等方式来解决状态共享和线程安全问题;同时,可以通过依赖注入、面向接口编程等方式降低对象之间的耦合度。


总结的说 : 单列模式可以节约内存,提高性能、但是会有变量污染,提高风险。


多例模式

在Spring框架中,多例模式(Prototype Pattern)是指每次获取对象实例时都会创建一个新的实例,相比于单例模式,多例模式具有以下优点和好处:


1. 灵活性:多例模式可以根据需求创建多个实例,每个实例可以有不同的状态和属性,提供了更大的灵活性和定制性。

2. 避免共享状态:多例模式每次创建新的实例,避免了多个对象之间共享状态的问题。每个实例都是独立的,互不影响。

3. 高并发性能:在高并发环境下,多例模式可以减少线程竞争,提高系统的并发性能。每个线程获取到的都是独立的实例,不会出现资源竞争的情况。

4. 避免单例模式的缺点:单例模式在某些场景下可能会存在线程安全问题、资源占用过多等缺点,而多例模式可以避免这些问题。

5. 降低耦合度:多例模式可以降低对象之间的耦合度,每个对象都是独立的,可以独立创建和销毁,不会产生过多的依赖关系。

6. 提供灵活的生命周期管理:多例模式可以通过Spring容器的生命周期管理功能来管理实例的创建和销毁,提供了更灵活的生命周期管理方式。

需要注意的是,多例模式也存在一些潜在的问题,比如对象的创建和销毁开销较大,可能会影响系统性能;多例模式可能会导致对象的过度创建,占用过多的系统资源。因此,在使用多例模式时需要根据具体的业务场景和性能需求进行权衡和选择。


在Spring框架中使用多例模式(Prototype Pattern)可能会存在以下缺点:


1. 资源消耗过多:每次获取多例对象时都会创建一个新的实例,这可能会导致系统资源的过度消耗。如果多例对象的创建和销毁过程比较复杂,可能会导致系统性能下降。

2. 难以管理和维护:多例模式创建的实例数量可能会很多,这会增加系统的复杂性和维护成本。如果没有良好的管理和控制机制,可能会导致实例过多、内存泄漏等问题。

3. 难以保证一致性:多例模式创建的实例是相互独立的,每个实例都有自己的状态和属性。这可能会导致系统中存在大量的不一致性,增加了系统的复杂性和调试难度。

4. 不适合共享资源:多例模式每次创建新的实例,不适合用于共享资源的场景。如果多个对象需要共享某些资源,可能需要额外的处理和同步机制。

需要根据具体的业务场景和性能需求来选择使用多例模式。在一些需要灵活性和定制性较高的场景下,多例模式可以提供更大的灵活性。但同时也需要注意管理和控制多例对象的数量,避免资源的过度消耗。


总结的说: 多列模式没有变量污染,没有风险,但是会非常消耗资源及内存。


3.2 演示

创建 ParamAction 类

package com.wenhao.bean;
import java.util.List;
/**
 * @author wenhao
 * @create  2023-08-18 13:44
 */
public class ParamAction {
    private int age;
    private String name;
    private List<String> hobby;
    private int num = 1;
    // private UserBiz userBiz = new UserBizImpl1();
    public ParamAction() {
        super();
    }
    public ParamAction(int age, String name, List<String> hobby) {
        super();
        this.age = age;
        this.name = name;
        this.hobby = hobby;
    }
    public void execute() {
        // userBiz.upload();
        // userBiz = new UserBizImpl2();
        System.out.println("this.num=" + this.num++);
        System.out.println(this.name);
        System.out.println(this.age);
        System.out.println(this.hobby);
    }
}


创建 InstanceFactory 类

package com.wenhao.bean;
/**
 * @author wenhao
 * @create  2023-08-18 13:42
 */
public class InstanceFactory {
    public void init() {
        System.out.println("初始化方法");
    }
    public void destroy() {
        System.out.println("销毁方法");
    }
    public void service() {
        System.out.println("业务方法");
    }
}


创建配置文件 spring-bean.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">
    <bean  class="com.wenhao.bean.ParamAction" id="paramAction" scope="prototype">
        <constructor-arg name="name" value="三丰"></constructor-arg>
        <constructor-arg name="age" value="21"></constructor-arg>
        <constructor-arg name="hobby">
            <list>
                <value>抽烟</value>
                <value>烫头</value>
                <value>大保健</value>
            </list>
        </constructor-arg>
    </bean>
    <bean id="instanceFactory" class="com.wenhao.bean.InstanceFactory"
          scope="singleton" init-method="init" destroy-method="destroy"></bean>
</beans>


创建测试类 Demo2

package com.wenhao.bean;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/*
 * spring    bean的生命週期
 * spring    bean的單例多例
 * @author wenhao
 * @create  2023-08-18 13:44
 *
 */
public class Demo2 {
    // 体现单例与多例的区别
    @Test
    public void test1() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-bean.xml");
//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-bean.xml");
        ParamAction p1 = (ParamAction) applicationContext.getBean("paramAction");
        ParamAction p2 = (ParamAction) applicationContext.getBean("paramAction");
        // System.out.println(p1==p2);
        p1.execute();
        p2.execute();
//        单例时,容器销毁instanceFactory对象也销毁;多例时,容器销毁对象不一定销毁;
        applicationContext.close();
    }
    // 体现单例与多例的初始化的时间点 instanceFactory
    @Test
    public void test2() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-bean.xml");
        InstanceFactory instanceFactory = (InstanceFactory) applicationContext.getBean("instanceFactory");
    }
    // BeanFactory会初始化bean对象,但会根据不同的实现子类采取不同的初始化方式
    // 默认情况下bean的初始化,单例模式立马会执行,但是此时XmlBeanFactory作为子类,单例模式下容器创建,bean依赖没有初始化,只有要获取使用bean对象才进行初始化
    @Test
    public void test3() {
        // ClassPathXmlApplicationContext applicationContext = new
        // ClassPathXmlApplicationContext("/spring-bean.xml");
        Resource resource = new ClassPathResource("/spring-bean.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");
    }
}


测试Demo2中的test1方法

使用单例模式测试结果

将spring-bean.xml 配置文件中的scope="prototype"修改

为scope="singleton"便是使用多例模式

使用多例模式测试结果


测试Demo2中的test2方法

( 提示: 当内容比较多时,可以在xml配置文件中修改单列或者多列模式继续运行速度测试 )

测试Demo2中的test3方法

BeanFactory会初始化bean对象,但会根据不同的实现子类采取不同的初始化方式

( 提示: 当内容比较多时,可以在xml配置文件中修改单列或者多列模式继续运行速度测试 )  


给我们带来什么收获


学习Spring框架中的JavaBean对我们有以下收获:


1. 灵活的开发方式:学习使用JavaBean可以帮助我们以一种更加灵活和可扩展的方式进行开发。JavaBean的依赖注入机制可以帮助我们实现松耦合的组件之间的交互,提高代码的可维护性和可测试性。

2. 提高开发效率:Spring框架提供了大量的现成的JavaBean组件,可以在我们的应用程序中直接使用。这些组件包括事务管理、持久化、安全验证等功能,可以节省我们自己编写这些功能代码的时间和精力,提高开发效率。

3. 更好的代码组织和管理:通过将应用程序中的不同功能模块拆分成各个JavaBean组件,可以使代码更具可读性、可维护性和可扩展性。JavaBean也可以作为数据模型,帮助我们将业务逻辑与数据操作分离,使代码更好地符合单一职责原则。

4. 使用Spring提供的功能和特性:学习使用JavaBean可以打开使用Spring框架更多功能和特性的大门。Spring提供了丰富的功能,如AOP、数据绑定、事务管理等,通过合理利用JavaBean,我们可以从中受益,提高应用程序的质量和性能。

5. 探索Java生态系统:JavaBean在Spring框架中的使用是我们进入更广阔Java生态系统的一扇门。Spring是Java生态系统中最流行的框架之一,掌握JavaBean的使用,有助于我们更好地理解和使用其他相关框架和技术。

综上所述,学习Spring框架中的JavaBean可以为我们带来诸多收获,包括灵活的开发方式、提高开发效率、更好的代码组织和管理,以及进一步探索Java生态系统的机会。掌握JavaBean的使用,可以使我们更加熟练地使用Spring框架,并在日常开发中取  

目录
相关文章
|
28天前
|
XML 安全 Java
|
5天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
5天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
10天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
45 6
|
12天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
67 3
|
29天前
|
Java 关系型数据库 数据库
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。
|
1月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
26天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
32 1
|
缓存 Java Spring
Spring 获取单例流程(三)
读完这篇文章你将会收获到 • Spring 何时将 bean 加入到第三级缓存和第一级缓存中 • Spring 何时回调各种 Aware 接口、BeanPostProcessor 、InitializingBean 等
129 0
|
缓存 Java Spring
Spring 获取单例流程(二)
读完这篇文章你将会收获到 • Spring 中 prototype 类型的 bean 如何做循环依赖检测 • Spring 中 singleton 类型的 bean 如何做循环依赖检测
85 0