Spring Framework中的Bean生命周期2

简介: Spring Framework中的Bean生命周期2

二. Bean的单例选择与多例选择

默认状态下Bean的配置的单例的,当然,也可以选择去配置多例的

1.单例选择与多例选择的优缺点

1.1单例模式的优点:

1.资源利用:单例模式在应用程序启动时创建一个实例,并一直重用该实例,减少了对象创建和销毁的开销,可以有效利用系统资源。

2.全局性:单例模式可以在整个应用程序中共享数据,确保数据的一致性和可靠性。

3.状态共享:由于单例只有一个实例,可以方便地在不同的组件之间共享状态,简化了组件之间的通信和数据传递。

4.线程安全:单例模式天生具有线程安全的特性,因为只有一个实例在操作,避免了并发访问的问题。

1.2单例模式的缺点:

1.资源持有:单例模式的实例会一直存在于内存中,占用一定的系统资源,在某些情况下可能会导致资源浪费。

2.生命周期管理:单例模式的实例生命周期长,无法自动释放资源,需要手动管理对象状态和清理资源。

3.难以模拟测试:由于单例模式的全局性和状态共享的特性,对于单元测试和模拟测试来说可能会更加困难,因为需要考虑到全局状态的影响。

1.3多例模式的优点:

1.灵活性:多例模式可以根据需要创建多个实例,每个实例之间相互独立并具有自己的状态,可以更灵活地应对不同的需求。

2.隔离性:多例模式的实例相互独立,不共享状态,可以避免状态污染和互相干扰的问题。

3.生命周期管理:每个多例实例的生命周期由Spring容器管理,可以自动释放资源,减少内存泄漏的风险。

4.更易于测试:多例模式的实例相互独立,可以更容易地进行单元测试和模拟测试,测试之间不会相互影响。

1.4多例模式的缺点:

1.资源占用:多例模式创建了多个实例,会占用更多的内存和系统资源。

2.对象管理复杂:多个实例需要由开发者自己管理和控制,需要注意实例的创建、销毁和状态管理,增加了设计和开发的复杂性。

3.线程安全:多例模式的实例在并发环境下需要额外考虑线程安全的问题,确保实例之间的数据不会冲突。

1.5 小结

单例模式适用于需要全局共享和状态共享的情况,能够提高资源利用和数据一致性,但需要注意资源管理和生命周期的维护。而多例模式适用于需要灵活性和隔离性的情况,能够减少资源占用和相互影响,但需要开发者自行管理和控制实例的创建和状态。选择单例还是多例取决于具体的业务需求和系统设计的考虑。

2.案例演示单例模式与多例模式

1.演示在单例模式和多例模式下资源变量是否被污染

1.准备好资源

package com.YU.beanlife;
import java.util.List;
import com.YU.ioc.service.UserService;
import com.YU.ioc.service.impl.UserServiceImpl1;
import com.YU.ioc.service.impl.UserServiceImpl2;
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);
  }
}

2.准备好Bean工厂

package com.YU.beanlife;
public class InstanceFactory {
  public void init() {
    System.out.println("初始化方法");
  }
  public void destroy() {
    System.out.println("销毁方法");
  }
  public void service() {
    System.out.println("业务方法");
  }
}

3.配置xml中的bean目录

<!--spring的生命周期-->
    <bean class="com.YU.beanlife.ParamAction" id="paramAction">
        <constructor-arg name="name" value="死仔"></constructor-arg>
        <constructor-arg name="age" value="21"></constructor-arg>
        <constructor-arg name="hobby">
            <list>
                <value>抽烟</value>
                <value>打go</value>
                <value>烫头</value>
            </list>
        </constructor-arg>
    </bean>
    <bean id="instanceFactory" class="com.YU.beanlife.InstanceFactory"
          scope="prototype" init-method="init" destroy-method="destroy"></bean>

4.编写测试程序

package com.YU.beanlife;
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的單例多例
 */
public class Demo2 {
  // 体现单例与多例的区别
  @Test
  public void test1() {
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.xml");
//    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-context.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-context.xml");
    InstanceFactory instanceFactory = (InstanceFactory) applicationContext.getBean("instanceFactory");
  }
  // BeanFactory会初始化bean对象,但会根据不同的实现子类采取不同的初始化方式
  // 默认情况下bean的初始化,单例模式立马会执行,但是此时XmlBeanFactory作为子类,单例模式下容器创建,bean依赖没有初始化,只有要获取使用bean对象才进行初始化
  @Test
  public void test3() {
    // ClassPathXmlApplicationContext applicationContext = new
    // ClassPathXmlApplicationContext("/spring-context.xml");
    Resource resource = new ClassPathResource("/spring-context.xml");
    BeanFactory beanFactory = new XmlBeanFactory(resource);
//    InstanceFactory i1 = (InstanceFactory) beanFactory.getBean("instanceFactory");
  }
}

其中Test1测试结果为:

由于我们默认使用的是单例模式,所以在运行时出现了变量污染,num值变为2

当我们配置多例模式同样运行Test1时

scope="prototype"

由此可得知我们的变量没有被污染

2. 判断单例模式和多例模式的初始化

配置和上面是一样的

1.当我们运行Test2时测试JavaBean是否跟着初始化

单例模式运行结果:

由单例模式可以看出发生了初始化

多例模式运行结果:

由此得知并没有出现初始化

当我们用多例模式运行Test3时

运行结果:

看到红框中的代码,当我们的JavaBean时才会初始化

小结:

由三次运行结果我们可以得出:

1.单例模式中的JavaBean是跟着Spring上下文初始化的,容器生成对象跟着生成,容器死亡,对象死亡

2.多例模式走的Javabean是使用时才会创建,销毁要跟着Jvm走

3.单例模式和多例模式的适用场景

单例模式和多例模式在不同的场景下具有不同的适用性。以下是它们常见的适用场景:

适用于单例模式的场景:

1.资源共享:当需要在应用程序的多个组件之间共享同一份资源或数据时,单例模式可以确保全局范围内的数据一致性。

2.工厂类:当需要创建一个全局工厂类来统一管理对象的创建和生命周期时,单例模式可以确保该工厂类始终只有一个实例。

3.配置信息:当需要在应用程序中加载一份全局的配置信息,并且多个组件需要共享该配置信息时,单例模式可以确保配置信息的一致性和高效访问。

4.日志记录器:当需要在整个应用程序中使用同一个日志记录器来记录日志时,单例模式可以确保日志的一致性和集中管理。

适用于多例模式的场景:

1.并发请求处理:当需要在多线程或并发环境下处理请求,并且每个请求使用独立的实例来保证状态隔离时,多例模式可以为每个请求创建一个独立的对象。

2.对象池:当需要管理一组可复用的对象,并且对象在不同的时刻需要创建和销毁时,多例模式可以提供对象池来管理对象的生命周期,以减少创建和销毁的开销。

3.状态管理:当对象的状态需要在不同的上下文环境中独立维护和处理时,多例模式可以为每个上下文环境创建一个独立的实例,以避免状态冲突和相互干扰。

4.服务提供者:当系统需要支持多个相同类型的服务提供者,并且每个服务提供者需要独立的实例时,多例模式可以满足服务提供者的创建和管理需求。

注意!!!

单例模式在一些场景下可能存在共享资源竞争、线程安全等问题,需要谨慎设计和考虑并发访问的情况。多例模式在一些场景下可能会增加资源消耗和对象管理的复杂性,需要权衡资源利用和代码复杂度之间的平衡。在实际应用中,根据具体的业务需求和系统设计要求来选择单例模式或多例模式。

很感谢各位大佬的观看,点个关注不迷路,大家的点赞和收藏是博主最大的创作动力,谢谢啦

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
5天前
|
Java uml Spring
手写spring第四章-完善bean实例化,自动填充成员属性
手写spring第四章-完善bean实例化,自动填充成员属性
14 0
|
11天前
|
Java 开发者 Spring
Spring Framework 中的 @Autowired 注解:概念与使用方法
【4月更文挑战第20天】在Spring Framework中,@Autowired 注解是实现依赖注入(Dependency Injection, DI)的一种非常强大的工具。通过使用 @Autowired,开发者可以减少代码中的引用绑定,提高模块间的解耦能力
31 6
|
4天前
|
前端开发 Java 数据格式
【Spring系列笔记】定义Bean的方式
在Spring Boot应用程序中,定义Bean是非常常见的操作,它是构建应用程序的基础。Spring Boot提供了多种方式来定义Bean,每种方式都有其适用的场景和优势。
17 2
|
5天前
|
XML Java 数据格式
手写spring第七章-完成便捷实现bean对象初始化和销毁方法
手写spring第七章-完成便捷实现bean对象初始化和销毁方法
6 0
|
5天前
|
XML Java 数据格式
手写spring第六章-实现应用上下文,完成bean的扩展机制
手写spring第六章-实现应用上下文,完成bean的扩展机制
11 0
|
5天前
|
设计模式 搜索推荐 Java
手写spring第三章-重构,使用依赖关系完善实例化bean操作
手写spring第三章-重构,使用依赖关系完善实例化bean操作
12 0
|
6天前
|
前端开发 Java Spring
Spring Framework五大功能模块
Spring Framework五大功能模块
|
6天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
13天前
|
设计模式 Java 数据库连接
Spring Framework 6 中的设计模式
Spring Framework 6 中的设计模式
21 1
|
14天前
|
Java 数据库连接 开发者
浅谈Spring的Bean生命周期
浅谈Spring的Bean生命周期
20 1