Bean
什麼是 Bean
構成應用程序最基本的對象。
由 Spring IOC 容器管理。
由 IOC 容器透過 BeanFactory 實例化、裝配與管理使用。
基於用戶提供給容器的資料創建。
生命週期
Bean的建立
由 BeanFactory 讀取 Bean 定義檔,並生成各個 Bean 實例。
屬性注入
執行相關的Bean屬性依賴注入。
BeanNameAware 的 setBeanName()
如果Bean類別有實作 BeanNameAware介面,則執行它的setBeanName()方法。
BeanFactoryAware 的 setBeanFactory()
如果Bean類別有實作 BeanFactoryAware介面,則執行它的setBeanFactory()方法。
BeanPostProcessors 的 processBeforeInitialization()
如果有任何的BeanPostProcessors實例與Bean實例關聯,則執行BeanPostProcessors實例的processBeforeInitialization()方法。
InitializingBean 的 afterPropertiesSet()
如果Bean類別有實作 InitializingBean,則執行它的afterPropertiesSet()方法。
BeanPostProcessors 的 processAfterInitialization()
如果有任何的BeanPostProcessors實例與Bean實例關聯,則執行BeanPostProcessors實例的processAfterInitialization()方法。
DisposableBean 的 destroy()
在容器關閉時,如果Bean類別有實作 DisposableBean,則執行它的destroy()方法。
Spring 提供自訂幾種方式
實作
InitializingBean
和DisposableBean
介面透過實作 特定行為的介面( Aware ),告訴Bean 必須有何種基礎結構依賴。
bean XML 配置default init() 或 destroy() 方法,針對單個或全局 Bean 使用 ; Spring 2.5 之後,也可以使用 @PostConstruct 和 @PreDestroy
Bean 範圍(@Scope)
Singleton
未指定 Scope 時的預設,每個 IOC 容器只會有一個實例,non-thread safe
。
Prototype
每次使用( .getBean )都會產生一次實例。
以下僅當支持 Web Application Context 時,才能使用
Request
每一次 HTTP 請求都會產生一次實例。該 Bean 僅在 當前 HTTP 請求 時有效。
Session
每一次 HTTP 請求都會產生一次實例。該 Bean 僅在 當前 HTTP Session 內時有效。
以下僅當支持 Web Application Context 時 且 在 portlet context,才能使用
Global-Session
只有在 portlet context 才會有用,屬於一種 HTTP session 全局共用的概念。
自動裝配
不使用 XML 、Java 來描述Bean,通過在相關的類別、方法或字段上面,使用註解將 XML 配置移動到物件類別本身,作為撰寫 XML 的替代方式,在 Spring 中,必須啟動 <context: annotation-config>
。
Bean 的自動裝配 Autowire
Spring 本身也可以自動裝配 Bean ,等同於 @Configuration + @Bean。
通過 BeanFactory 讓 Spring 自動解析 Bean 的內容。
模式
no - 預設行為,表示沒有裝配。
byName - 根據名稱注入依賴項,匹配與 XML 文件同名稱的 Bean 。
byType - 根據類型注入依賴項,屬性類型匹配與 XML 文件同名稱的 Bean 。
constructor - 根據建構子注入依賴項,匹配擁有相同建構子的 Bean 。
autodetect - 通過自動檢測注入依賴項,兩種模式之一 即 constructor 或 byType。
順序為:符合 constructor ->> 無參數 constructor ->> byType 模式。
Spring 5.1 已棄用,@Autowired 已經取代了 name/type-based 注入方式。 as of 5.1, since {@code @Bean} factory method argument resolution and * {@code @Autowired} processing supersede name/type-based bean property injection
@Bean 使用方式
基於註解 - @Component / @ComponentScan
將會把此類別標註為 Bean,此為管理 Spring 組件的通用構造,Spring 組件的掃描機制 @ComponentScan
會在 IOC 容器中取得並拉入應用環境。
Ex : @Controller、@Service、@Repository、@Configuration 基礎構造皆透過此註解。
在執行 simpleBeanConsumer 時,每次調用 simple() 都會取得一個全新的 Simple 實例,在全局中就會擁有多個實例。
基於 Java - @Configuration
包含 @Component 標註,且所有帶有 @Bean 註解的方法都會被動態代理(JDK代理、CGlib)。
動態代理的主要原因,@Configuration 註解設定了:
配置類別必須以 新建立對象 提供(不能使用 工廠方法 產生的實例)。
配置類別不能具有 final 關鍵字,否則無法動態代理,必須允許通過生成子類別在運行時增強(CGlib 動態代理)。
類別必須是非方法內產生,或非具有 private 關鍵字。
通常是為了生成讓 Spring container 管理的類別。
任何嵌入的配置類別都必須具有 static 關鍵字(即內部在嵌入配置類別)。
若方法是首次被呼叫,那麼原始的方法被執行並且結果對象會被註冊到Spring IOC 容器中,
之後所有對該方法的呼叫僅僅是從Spring IOC 容器中取回該對象返回給呼叫者。
思考
若 @Configuration 不想要被動態代理,或者希望 @Component 的對象皆為一致。
參考資料
Last updated
Was this helpful?