原型範圍

在 Spring 容器啟動時不預先建立原型範圍的 bean。相反,每次將檢索此 bean 的請求傳送到容器時,都會建立一個新的例項。建議將此範圍用於有狀態物件,因為其狀態不會被其他元件共享。

為了定義原型範圍的 bean,我們需要新增 @Scope 註釋,指定我們想要的範圍型別。

給出以下 MyBean 類:

public class MyBean {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyBean.class);
    private String property;

    public MyBean(String property) {
        this.property = property;
        LOGGER.info("Initializing {} bean...", property);
    }

    public String getProperty() {
        return this.property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}

我們定義一個 bean 定義,將其範圍說明為原型:

@Configuration
public class PrototypeConfiguration {

    @Bean
    @Scope("prototype")
    public MyBean prototypeBean() {
        return new MyBean("prototype");
    }
}

為了瞭解它是如何工作的,我們從 Spring 容器中檢索 bean 併為其屬性欄位設定不同的值。接下來,我們將再次從容器中檢索 bean 並查詢其值:

MyBean prototypeBean1 = context.getBean("prototypeBean", MyBean.class);
prototypeBean1.setProperty("changed property");

MyBean prototypeBean2 = context.getBean("prototypeBean", MyBean.class);

logger.info("Prototype bean 1 property: " + prototypeBean1.getProperty());
logger.info("Prototype bean 2 property: " + prototypeBean2.getProperty());

檢視以下結果,我們可以看到如何在每個 bean 請求上建立一個新例項:

Initializing prototype bean...
Initializing prototype bean...
Prototype bean 1 property: changed property
Prototype bean 2 property: prototype

一個常見的錯誤是假設每次呼叫或每個執行緒都重新建立 bean,但事實並非如此。而是建立 PER INJECTION(或從上下文中檢索)例項。如果 Prototype 作用域 bean 只被注入一個單獨的 bean,那麼只有一個 Prototype 作用域 bean 的例項。

Spring 不管理原型 bean 的完整生命週期:容器例項化,配置,裝飾和組裝原型物件,將其交給客戶端,然後不再瞭解該原型例項。