IOC(bean的作用域与生命周期)

  bean作用域

    单例和多例

    1 . 什么是单例和多例

            单例 (singleton):所有请求用同一个对象来处理。通过单例模式,可以保证系统中一个类只有一个实例。

           多例 (prototype):每个请求用一个新的对象来处理。

      如果一个bean被声明为单例的时候,在处理多次请求的时候,

      在spring容器里只实例化出一个bean,后续的请求都公用这个对象,

     这个对象会保存在一个map里面。

      但是对于原型(prototype)bean来说,当每次请求来的时候,会直接实例化新的bean,

       没有缓存以及缓存查询的过程。

      2 . 为什么用单例和多例

                之所以用单例:是因为没必要每个请求都新建一个对象,这样子既浪费CPU又浪费内存;

                之所以用多例:是为了防止并发问题;即一个请求改变了对象的状态,

                                           此时对象又处理另一个请求,而之前请求对对象状态的改变导致了

                                          对象对另一个请求做了错误的处理;

        用单例和多例的标准只有一个:

                           当对象含有可改变的状态时(更精确的说就是在实际应用中该状态会改变),则多例,否则单例;

               在 Spring 中可以通过配置 bean 标签的 scope 属性来指定 bean 的作用域范围:

取值含义创建对象的时机默认值
singleton 在 IOC 容器中,这个 bean 的对象始终为单实例 IOC 容器初始化时
prototype 这个 bean 在 IOC 容器中有多个实例 获取 bean 时

                       如果是在WebApplicationContext环境下还会有另外两个作用域(但不常用):

取值含义
request 在一个请求范围内有效
session 在一个会话范围内有效

 

<!--
  scope:设置bean的作用域
  scope:"singleton/prototype"
  singleton(单例):表示获取该bean所对应的对象都是同一个 (默认,用的也最多)
  prototype(多例):表示获取该bean所对应的对象都不是同一个
    -->
<bean id="student" class="com.atguigu.spring.pojo.Student" scope="prototype"></bean>
@Test
   public void testScope(){
       ApplicationContext ioc=new ClassPathXmlApplicationContext("ApplicationContext.xml");
       Student bean1 = ioc.getBean(Student.class);
       Student bean2 = ioc.getBean(Student.class);
       System.out.println(bean1==bean2);
       //结果为:false
  }

 

   bean生命周期

      1 . bean的生命周期清单

  • bean 对象创建(调用无参构造器)

  • 给 bean 对象设置属性(调用属性对应的 setter 方法)

  • bean 对象初始化之前操作(由 bean 的后置处理器postProcessBeforInitalization负责)

  • bean 对象初始化(需在配置 bean 时指定初始化方法)

  • bean 对象初始化之后操作(由 bean 的后置处理器负责)

  • bean 对象就绪可以使用

  • bean 对象销毁(需在配置 bean 时指定销毁方法)

  • IOC 容器关闭

   注意:若bean的作用域为单例时,生命周期的前三个步骤会在获取IOC容器时执行
若bean的作用域为多例时,生命周期的前三个步骤会在获取bean的时候执行
package com.atguigu.spring.pojo;

public class User {
   private Integer id;
   private String username;
   private String password;
   private Integer age;
   
   public User() {
       System.out.println("生命周期1:实例化");
  }

   public User(Integer id, String username, String password, Integer age) {
       this.id = id;
       this.username = username;
       this.password = password;
       this.age = age;
  }
   public Integer getId() {
       return id;
  }
   public void setId(Integer id) {
       System.out.println("生命周期2:依赖注入(为属性赋值)");
       this.id = id;
  }
   
....
  ....
     
   public void initMethod(){
       System.out.println("生命周期3:初始化");
  }
   public void destroyMethod(){
       System.out.println("生命周期4:销毁");
  }
}
<!--  
   设置初始化和销毁的过程,需要通过bean标签的属性来进行指定
   销毁的方法是当前IOC容器关闭的时候才会销毁
-->
   <bean id="user" class="com.atguigu.spring.pojo.User" init-method="initMethod" destroy-method="destroyMethod">
       <property name="id" value="1"></property>
       <property name="username" value="admin"></property>
       <property name="password" value="123456"></property>
       <property name="age" value="23"></property>
   </bean>

   /**
    * ①实例化--> ②依赖注入 -->③初始化:需要通过bean的init-method属性指定初始化方法--->IOC容器关闭销毁:destroy-method
    */
   @Test
   public void test(){
       //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
       ConfigurableApplicationContext ioc=new ClassPathXmlApplicationContext("ApplicationContext.xml");
       User bean = ioc.getBean(User.class);
       System.out.println(bean);
//   ApplicationContext:没有提供刷新和关闭容器的功能,是他的一个子接口来提供的
       ioc.close();
       /**
        * 生命周期1:实例化
        * 生命周期2:依赖注入(为属性赋值)
        * 生命周期3:初始化
        * User{id=1, username='admin', password='123456', age=23}
        * 生命周期4:销毁
        */
  }
posted @ 2022-11-13 18:29  zjw_rp  阅读(132)  评论(0)    收藏  举报