Spring Framework ‐ Bean Scope - CCH0124/spring-sandbox GitHub Wiki

Spring 框架定義了 6 種類型的 Bean 作用域:

  • singleton
    • Spring 容器實例化一次,請求它的所有物件將會共用實例
  • prototype
    • 表示每次對其發出請求時,Spring 容器都會建立該 Bean 的新實例
  • request
    • 僅適用於 Web 應用程式(),表示 Spring 容器為每個 HTTP 請求建立一個新的 Bean 實例
  • session
    • 一旦更改該物件的值,該值將保留用於後續請求,因為為整個會話傳回相同的 Bean 實例
  • application
    • todo
  • websocket
    • todo

Singleton Scope

如果定義一個單例作用域的 Bean 時,Spring 中容器會建立該 Bean 的唯一實例,對該 Bean 名稱的所有請求都將返回相同的物件。

下面範例引用同一個 Bean 的兩個物件將具有相同的值,就算其中一個物件更改其狀態其所對應之物件還是相同,因為它們都引用同一個 Bean 實例

    @Bean
    @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
    public Cat catSingleton() {
        return new Cat("Hello", 3);
    }
    @Test
    public void givenSingletonScope_whenSetName_thenEqualNames() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScopeConfig.class);

        Cat catSingletonA = (Cat) applicationContext.getBean("catSingleton");
        Cat catSingletonB = (Cat) applicationContext.getBean("catSingleton");
        catSingletonA.setName("set");
        assertEquals(catSingletonA.getName(), catSingletonB.getName());

        ((AbstractApplicationContext) applicationContext).close();
    }

Prototype Scope

每次從 Spring 容器請求時,具有 Prototype 屬性的 Bean 都會傳回不同的實例。

下面測試顯示兩個物件請求具有 Prototype 屬性的相同 Bean 名稱。它們將具有不同的狀態,因為它們不引用同一個 Bean 實例。

    @Bean
    @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Cat catPrototype() {
        return new Cat();
    }
    @Test
    public void givenPrototypeScope_whenSetNames_thenDifferentNames() {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScopeConfig.class);

        Cat catPrototypeA = (Cat) applicationContext.getBean("catPrototype");
        Cat catPrototypeB = (Cat) applicationContext.getBean("catPrototype");

        catPrototypeA.setName("Ragdoll");
        catPrototypeB.setName("American Shorthair");

        assertEquals("Ragdoll", catPrototypeA.getName());
        assertEquals("American Shorthair", catPrototypeB.getName());

        ((AbstractApplicationContext) applicationContext).close();
    }

baeldung | spring-bean-scopes