Spring IOC的高級(jí)特性???
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
? 作者?|??鄧曉暉
來源 |? urlify.cn/QfayQn
66套java從入門到精通實(shí)戰(zhàn)課程分享
1. lazy-Init延遲加載
Bean對(duì)象的延遲加載(延遲創(chuàng)建)
ApplicationContext 容器的默認(rèn)?為是在啟動(dòng)服務(wù)器時(shí)將所有 singleton bean 提前進(jìn)?實(shí)例化。提前實(shí)例化意味著作為初始化過程的?部分,ApplicationContext實(shí)例會(huì)創(chuàng)建并配置所有的singleton bean。
1.1 XML方式開啟延遲加載:
lazy-init="" 配置bean對(duì)象的延遲加載 ,true或者false false就是立即加載
"lazyResult"?class="com.lagou.edu.pojo.Result"?lazy-init="false">
我們先來看一下當(dāng)lazy-init="false"?也就是立即加載的時(shí)候:

可以看到,在容器啟動(dòng)后,getBean之前,lazyResult這個(gè)bean已經(jīng)存在了。
然后我們把lazy-init="true",設(shè)置為true
然后我們F8往下走一步:
發(fā)現(xiàn)出現(xiàn)了lazyResult
1.2 注解開啟延遲加載:
@Lazy:
1.3全局配置——default-lazy-init="":
在bean的根標(biāo)簽中:
應(yīng)用場(chǎng)景:
(1)開啟延遲加載?定程度提?容器啟動(dòng)和運(yùn)轉(zhuǎn)性能
(2)對(duì)于不常使?的 Bean 設(shè)置延遲加載,這樣偶爾使?的時(shí)候再加載,不必要從?開始該 Bean 就占?資源
2. FactoryBean和BeanFactory
2.1 BeanFactory
容器的頂級(jí)接口,定義了容器的一些基礎(chǔ)行為,負(fù)責(zé)生產(chǎn)和管理Bean的一個(gè)工廠,具體使用它下面的子接口類型,比如ApplicationContext
2.2 FactoryBean
spring中的bean有兩種
普通bean
工廠bean(FactoryBean)
可以生產(chǎn)某一個(gè)類型的bean實(shí)例(返回給我們),也就是說我們可以借助于它自定義bean的創(chuàng)建過程。
Bean創(chuàng)建的三種?式中的靜態(tài)?法和實(shí)例化?法和FactoryBean作?類似,F(xiàn)actoryBean使?較多,尤其在Spring框架?些組件中會(huì)使?,還有其他框架和Spring框架整合時(shí)使?
//可以讓我們自定義Bean的創(chuàng)建過程,完成復(fù)雜bean定義
public?interface?FactoryBean?{
?//返回FactoryBean創(chuàng)建的實(shí)例,如果isSingleton返回true,則該實(shí)例會(huì)放到Spring容器的單例緩存池中Map
?@Nullable
?T?getObject()?throws?Exception;
????//返回FactoryBean創(chuàng)建的bean類型
?@Nullable
?Class>?getObjectType();
?//返回作用域是否單例
?default?boolean?isSingleton()?{
??return?true;
?}
}
2.2.1 新建類CompanyFactoryBean,實(shí)現(xiàn)FactoryBean接口,并重寫方法:
public?class?CompanyFactoryBean?implements?FactoryBean?{
????private?String?companyInfo;//注入公司名稱,地址,規(guī)模??以逗號(hào)分隔
????public?void?setCompanyInfo(String?companyInfo)?{
????????this.companyInfo?=?companyInfo;
????}
????@Override
????public?Company?getObject()?throws?Exception?{
????????//創(chuàng)建復(fù)雜對(duì)象Company
????????Company?company=new?Company();
????????String[]?split?=?companyInfo.split(",");
????????company.setName(split[0]);
????????company.setAddress(split[1]);
????????company.setScale(Integer.parseInt(split[2]));
????????return?company;
????}
????@Override
????public?Class>?getObjectType()?{
????????//返回bean的類型
????????return?Company.class;
????}
????@Override
????public?boolean?isSingleton()?{
????????//是否是單例
????????return?true;
????}
}
public?class?Company?{
????private?String?name;
????private?String?address;
????private?int?scale;
?//省略getset?和toString
}
2.2.2 xml文件中配置bean
"companyBean"?class="com.lagou.edu.factory.CompanyFactoryBean">
???"companyInfo"?value="拉鉤,中關(guān)村,500">
2.2.3 測(cè)試
[email protected]
????public?void?test(){
????????ApplicationContext?applicationContext?=?new?ClassPathXmlApplicationContext("applicationContext.xml");
????????Object?companyBean?=?applicationContext.getBean("companyBean");
????????System.out.println(companyBean);
????}
//結(jié)果返回的是?Company{name='拉鉤',?address='中關(guān)村',?scale=500}???
雖然在xml配置文件中配置的bean的class="com.lagou.edu.factory.CompanyFactoryBean"?但是返回的Company類型。
如何返回CompanyFactoryBean類型呢?

打印結(jié)果為:com.lagou.edu.factory.CompanyFactoryBean@545b995e
3. 后置處理器
Spring提供了兩種后處理bean的擴(kuò)展接?,分別為?BeanPostProcessor?和BeanFactoryPostProcessor,兩者在使?上是有所區(qū)別的。
??初始化(BeanFactory)—> Bean對(duì)象
在BeanFactory初始化之后可以使?BeanFactoryPostProcessor進(jìn)?后置處理做?些事情
在Bean對(duì)象實(shí)例化(并不是Bean的整個(gè)?命周期完成)之后可以使?BeanPostProcessor進(jìn)?后置處理做?些事情
注意:對(duì)象不?定是springbean,?springbean?定是個(gè)對(duì)象
3.1 SpringBean生命周期圖

按照上述描述的打印一下。看看是否一致:
//實(shí)現(xiàn)了BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean,DisposableBean接口
public?class?Result?implements?BeanNameAware,?BeanFactoryAware,?ApplicationContextAware,?InitializingBean,?DisposableBean?{
????private?String?status;
????private?String?message;
?//省略getset?toString方法
????@Override
????public?void?setBeanFactory(BeanFactory?beanFactory)?throws?BeansException?{
????????System.out.println("4.BeanFactoryAware:"+beanFactory);
????}
????@Override
????public?void?setBeanName(String?name)?{
????????System.out.println("3.BeanNameAware:"+name);
????}
????@Override
????public?void?setApplicationContext(ApplicationContext?applicationContext)?throws?BeansException?{
????????System.out.println("5.ApplicationContextAware:"+applicationContext);
????}
????@Override
????public?void?afterPropertiesSet()?throws?Exception?{
????????System.out.println("7.InitializingBean");
????}
????public?void?initMethodTest(){
????????System.out.println("8.initMethod");
????}
????@PostConstruct
????public?void?postCoustrcut(){
????????System.out.println("postCoustrcut");
????}
????//銷毀之前執(zhí)行
????@PreDestroy
????public?void?preDestroy(){
????????System.out.println("銷毀之前執(zhí)行");
????}
????@Override
????public?void?destroy()?throws?Exception?{
????????System.out.println("DisposableBean");
????}
}
/**
????攔截實(shí)例化之后的對(duì)象(實(shí)例化了?并且屬性注入了)
????攔截所有的
?*/
@Component
public?class?MyBeanPostProcessor?implements?BeanPostProcessor?{
????@Override
????public?Object?postProcessBeforeInitialization(Object?bean,?String?beanName)?throws?BeansException?{
????????if?("lazyResult".equalsIgnoreCase(beanName)){
????????????System.out.println("MyBeanPostProcessor?before");
????????}
????????return?bean;
????}
????@Override
????public?Object?postProcessAfterInitialization(Object?bean,?String?beanName)?throws?BeansException?{
????????if?("lazyResult".equalsIgnoreCase(beanName)){
????????????System.out.println("MyBeanPostProcessor?After");
????????}
????????return?bean;
????}
}
//XML配置文件中:????
"lazyResult"?class="com.lagou.edu.pojo.Result"??init-method="initMethodTest">
//測(cè)試:
[email protected]
????public?void?testBeanLazy(){
????????ClassPathXmlApplicationContext?applicationContext?=?new?ClassPathXmlApplicationContext("classpath:applicationContext.xml");
????????Object?lazyResult?=??applicationContext.getBean("lazyResult");
????????System.out.println(lazyResult);
????????applicationContext.close();
????}
打印出:
4. 其他:

粉絲福利:實(shí)戰(zhàn)springboot+CAS單點(diǎn)登錄系統(tǒng)視頻教程免費(fèi)領(lǐng)取
???
?長(zhǎng)按上方微信二維碼?2 秒 即可獲取資料
感謝點(diǎn)贊支持下哈?
