首頁  >  文章  >  Java  >  Java之Spring Bean作用域與生命週期的深入分析與原始碼解析

Java之Spring Bean作用域與生命週期的深入分析與原始碼解析

WBOY
WBOY轉載
2023-05-08 19:04:06827瀏覽

Bean 作用域與生命週期

Bean 作用域

Bean 的作用域是指Bean 在Spring 整個框架中的某種行為模式.

#例如singleton 單例作用域, 就表示Bean 在整個Spring 中只有一份, 它是全域共享的, 那麼當其他人修改了這個值之後, 那麼另一個人讀取到的就是被修改的值.

Bean 作用域分類

  • singleton: 單例作用域(預設作用域)

  • ##prototype: 原型作用域(多例作用域)

  • request: 請求作用域

  • session: 回話作用域

  • application: 全域作用域

  • websocket: HTTP

# 注意# 後4 種狀態是Spring MVC 中的值,在普通的Spring 項⽬中只有前兩種.

singleton
Bean 預設情況下是單例狀態(singleton),也就是所有⼈的使⽤的都是同⼀個對象,之前我們學單例模式的時候都知道,使用單例可以很大程度上提高性能,所以在Spring 中Bean 的作用域默認也是singleton 單例模式。

  • 說明:此作用域下的Bean 在IoC 容器中只存在⼀個實例:取得Bean(即透過applicationContext.getBean 等方法取得)及組裝Bean(即透過 @Autowired 注入)都是同⼀個物件.

  • 場景:通常無狀態的Bean 使用此作用域.(無狀態表示Bean 物件的屬性狀態不需要更新)

prototype
  • 說明:每次對此作用域下的Bean 的請求都會建立新的實例:取得Bean(即透過applicationContext. getBean 等方法取得)及組裝Bean(即透過@Autowired 注入)都是新的物件實例。

  • 場景:通常有狀態的Bean使⽤該作用域.

request
  • 描述:每次http 請求都會建立新的Bean 實例,類似prototype

  • #場景:⼀次http 的請求和回應的共用Bean

  • #備註:限定SpringMVC 中使⽤

session
  • 描述:在⼀個http session 中,定義⼀個Bean 實例

  • 場景:⽤戶回話的共享Bean , 例如: 記錄⼀個⽤戶的登陸資訊

  • 備註:限定SpringMVC 中使⽤

application (了解)

  • #說明:在⼀個http servlet Context 中,定義⼀個Bean 實例

  • 場景:Web 應⽤的上下文資訊, 例如:記錄⼀個應用程式的共享資訊

  • 備註:限定SpringMVC 中使⽤

websocket (了解)

  • #描述:在⼀個HTTP WebSocket 的⽣命週期中,定義⼀個Bean 實例

  • 場景:WebSocket 的每次會話中,保存了⼀個Map 結構的頭訊息,將⽤來包裹客戶端訊息頭。第⼀次初始化後,直到 WebSocket 結束都是同⼀個 Bean。

  • 備註:限定Spring WebSocket 中使⽤

單例作用域(singleton) VS 全域作用域(application)

  • singleton 是Spring Core 的作用域, application 是Spring Web 中的作用域.

  • singleton 作用於IoC 的容器, application 作用於Servlet 容器

Bean 作用域的設定

@Scope 標籤既可以修飾⽅法也可以修飾類,@Scope 有兩種設定⽅式

使⽤枚舉設定:

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

@Component
public class UserBeans {
  	@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Bean
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Gujiu");
        user.setPassword("123456");
        return user;
    }
}

#直接設定值: 

#@Scope("prototype" )

@Component
public class UserBeans {
    @Scope("prototype")
    @Bean
    public User user1() {
        User user = new User();
        user.setId(1);
        user.setName("Gujiu");
        user.setPassword("123456");
        return user;
    }
}

Spring 執行流程

  • #啟動容器(啟動專案)

  • 讀取設定檔(初始化)

    • 使用 

      xml 直接註冊Bean

    • 設定 

      Bean 根(掃描) 路徑

  • 將Bean 儲存到 

    Spring 中: 透過類別註解進行掃描和組裝

  • #將

    Bean 組裝到需要的類別中(取操作)

#Bean 生命週期

所謂的⽣命週期指的是⼀個物件從誕⽣到銷毀的整個⽣命過程,我們把這個過程就叫做⼀個物件的⽣命週期。

Bean 的生命週期:

  • 實例化Bean (對應JVM 中的「載入」, 從無到有, 將字節碼轉換成內存中的物件, 只是分配了記憶體) [買了一套毛坯房]

  • 設定屬性(Bean 的注入與組裝) [購買裝潢材料(引入外部資源)]

  • Bean 初始化[房子裝潢]

    • 实现了各种 Aware 通知的方法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接口方法 [打电话给各个装修的师傅]

    • 执行 BeanPostProcessor 初始化前置方法 [师傅勘察环境, 指定装修方案 (前置工作)]

    • 执行 @PostConstruct 初始化方法,依赖注入操作之后被执行 [两类装修师傅进行装修]

    • 执行自己指定的 init-method 方法 (如果有指定的话) [两类装修师傅进行装修]

    • 执行 BeanPostProcessor 初始化后置方法 [装修之后的清理工作]

  • 使用 Bean [房子可以入住使用了]

  • 销毁 Bean [卖掉房子]

生命周期演示

BeanLifeComponent 类:

//@Component
public class BeanLifeComponent implements BeanNameAware {

    @Override
    public void setBeanName(String s) {
        System.out.println("执行了通知");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("执行了 @PostConstruct");
    }

    public void init() {
        System.out.println("执行了 init-method");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("执行了销毁方法");
    }
}

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"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="myComponent" class="com.demo.component.BeanLifeComponent"
          init-method="init" ></bean>
</beans>

调用类:

public class App2 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("spring-config.xml");
        BeanLifeComponent beanLifeComponent =
                applicationContext.getBean("myComponent", BeanLifeComponent.class);
        System.out.println("使用Bean");
        applicationContext.destroy();
    }
}

运行结果展示:

Java之Spring Bean作用域與生命週期的深入分析與原始碼解析

以上是Java之Spring Bean作用域與生命週期的深入分析與原始碼解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除