您好,登錄后才能下訂單哦!
本篇內容介紹了“Spring-IOC的高級特性有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
Bean的延遲加載(延遲創建)
ApplicationContext 容器的默認行為是在啟動服務器時將所有 singleton bean 提前進行實例化。提前實例化意味著作為初始化過程的?部分,ApplicationContext 實例會創建并配置所有的singleton bean。
比如:
<bean id="testBean" class="cn.bxc.LazyBean" /> 該bean默認的設置為: <bean id="testBean" calss="cn.bxc.LazyBean" lazy-init="false" />
lazy-init="false",立即加載,表示在spring啟動時,立刻進行實例化。如果不想讓?個singleton bean 在 ApplicationContext實現初始化時被提前實例化,那么可以將bean設置為延遲實例化。
<bean id="testBean" calss="cn.bxc.LazyBean" lazy-init="true" />
設置 lazy-init 為 true 的 bean 將不會在 ApplicationContext 啟動時提前被實例化,而是第?次向容器通過 getBean 索取 bean 時實例化的。
如果?個設置了立即加載的 bean1,引用了?個延遲加載的 bean2 ,那么 bean1 在容器啟動時被實例化,而 bean2 由于被 bean1 引用,所以也被實例化,這種情況也符合延時加載的 bean 在第?次調用時才被實例化的規則。
也可以在容器層次中通過在 元素上使用 "default-lazy-init" 屬性來控制延時初始化。如下面配置:
<beans default-lazy-init="true"> <!-- no beans will be eagerly pre-instantiated... --> </beans>
如果?個 bean 的 scope 屬性為 scope="pototype" 時,即使設置了 lazy-init="false",容器啟動時也不
會實例化bean,而是調用 getBean 方法實例化的。
應用場景
(1)開啟延遲加載?定程度提高容器啟動和運轉性能
(2)對于不常使用的 Bean 設置延遲加載,這樣偶爾使用的時候再加載,不必要從?開始該 Bean 就占用資源
BeanFactory接口是容器的頂級接口,定義了容器的?些基礎行為,負責生產和管理Bean的?個工廠,具體使用它下面的子接口類型,比如ApplicationContext;此處我們重點分析FactoryBean
Spring中Bean有兩種,?種是普通Bean,?種是工廠Bean(FactoryBean),FactoryBean可以生成某?個類型的Bean實例(返回給我們),也就是說我們可以借助于它自定義Bean的創建過程。
Bean創建的三種方式中的靜態方法和實例化方法和FactoryBean作用類似,FactoryBean使用較多,尤其在Spring框架?些組件中會使用,還有其他框架和Spring框架整合時使用
// 可以讓我們?定義Bean的創建過程(完成復雜Bean的定義) public interface FactoryBean<T> { @Nullable // 返回FactoryBean創建的Bean實例,如果isSingleton返回true,則該實例會放到Spring容器 的單例對象緩存池中Map T getObject() throws Exception; @Nullable // 返回FactoryBean創建的Bean類型 Class<?> getObjectType(); // 返回作?域是否單例 default boolean isSingleton() { return true; } }
Company類
package com.bxc.edu.pojo; /** * @author bixc */ public class Company { private String name; private String address; private int scale; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getScale() { return scale; } public void setScale(int scale) { this.scale = scale; } @Override public String toString() { return "Company{" + "name='" + name + '\'' + ", address='" + address + '\'' + ", scale=" + scale + '}'; } }
CompanyFactoryBean類
package com.bxc.edu.factory; import com.bxc.edu.pojo.Company; import org.springframework.beans.factory.FactoryBean; /** * @author bixc */ public class CompanyFactoryBean implements FactoryBean<Company> { private String companyInfo; // 公司名稱,地址,規模 public void setCompanyInfo(String companyInfo) { this.companyInfo = companyInfo; } @Override public Company getObject() throws Exception { // 模擬創建復雜對象Company Company company = new Company(); String[] strings = companyInfo.split(","); company.setName(strings[0]); company.setAddress(strings[1]); company.setScale(Integer.parseInt(strings[2])); return company; } @Override public Class<?> getObjectType() { return Company.class; } @Override public boolean isSingleton() { return true; } }
xml配置
<bean id="companyBean" class="com.bxc.edu.factory.CompanyFactoryBean"> <property name="companyInfo" value="阿里,中關村,500"/> </bean>
測試,獲取FactoryBean產生的對象
Object companyBean = applicationContext.getBean("companyBean"); System.out.println("bean:" + companyBean); // 結果如下 bean:Company{name='阿里', address='中關村', scale=500}
測試,獲取FactoryBean,需要在id之前添加“&”
Object companyBean = applicationContext.getBean("&companyBean"); System.out.println("bean:" + companyBean); // 結果如下 bean:com.bxc.edu.factory.CompanyFactoryBean@53f6fd09
Spring提供了兩種后處理bean的擴展接口,分別為 BeanPostProcessor 和BeanFactoryPostProcessor,兩者在使用上是有所區別的。
工廠初始化(BeanFactory)—> Bean對象
在BeanFactory初始化之后可以使用BeanFactoryPostProcessor進行后置處理做?些事情
在Bean對象實例化(并不是Bean的整個生命周期完成)之后可以使用BeanPostProcessor進行后置處理做?些事情
注意:對象不?定是springbean,而springbean一定是個對象
BeanPostProcessor
BeanPostProcessor是針對Bean級別的處理,可以針對某個具體的Bean.
該接口提供了兩個方法,分別在Bean的初始化方法前和初始化方法后執行,具體這個初始化方法指的是什么方法,類似我們在定義bean時,定義了init-method所指定的方法
定義?個類實現了BeanPostProcessor,默認是會對整個Spring容器中所有的bean進行處理。如果要對具體的某個bean處理,可以通過方法參數判斷,兩個類型參數分別為Object和String,第?個參
數是每個bean的實例,第?個參數是每個bean的name或者id屬性的值。所以我們可以通過第?個參數,來判斷我們將要處理的具體的bean。
注意:處理是發生在Spring容器的實例化和依賴注?之后。
BeanFactoryPostProcessor
BeanFactory級別的處理,是針對整個Bean的工廠進行處理,典型應用:PropertyPlaceholderConfigurer
此接口只提供了?個方法,方法參數為ConfigurableListableBeanFactory,該參數類型定義了?些方法
其中有個方法名為getBeanDefinition的方法,我們可以根據此方法,找到我們定義bean 的BeanDefinition對象。然后我們可以對定義的屬性進行修改,以下是BeanDefinition中的方法
方法名字類似我們bean標簽的屬性,setBeanClassName對應bean標簽中的class屬性,所以當我們拿到BeanDefinition對象時,我們可以手動修改bean標簽中所定義的屬性值。
BeanDefinition對象:我們在 XML 中定義的 bean標簽,Spring 解析 bean 標簽成為?個 JavaBean,這個JavaBean 就是 BeanDefinition
注意:調用 BeanFactoryPostProcessor 方法時,這時候bean還沒有實例化,此時 bean 剛被解析成BeanDefinition對象
“Spring-IOC的高級特性有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。