代碼位址
spring02
覺得部落客還可以給個Star
Spring Bean的生命周期
-
如何判斷Bean初始化了
初始化:指的是對象已經建立并且裡面所有的set已經全部執行完畢
在@Bean中有着initMethod,destoryMethod屬性,他們代表着bean被初始化和銷毀
具體用法:
UserEntity.java
package com.entity;
public class UserEntity {
public UserEntity(){
System.out.println("UserEntity無參構造...");
}
private void initMsg() {
System.out.println("UserEntity initMsg");
}
private void destroyMsg() {
System.out.println("UserEntity destroyMsg");
}
}
MyConfig.java
@Configuration
@ComponentScan("com.entity")
public class MyConfig {
@Bean(initMethod = "initMsg",destroyMethod = "destroyMsg")
public UserEntity userEntity(){
return new UserEntity();
}
}
Application.java
import com.config.MyConfig;
import com.entity.UserEntity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
// ApplicationContext
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
UserEntity userEntity = annotationConfigApplicationContext.getBean("userEntity", UserEntity.class);
}
}
運作結果:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL0AjMxIjM1EjMzIjMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
我們會發現"UserEntity destroyMsg"并未被列印出來,那是因為容器并未被銷毀,是以我們可以自己關閉容器,清除裡面的bean
Application.java
import com.config.MyConfig;
import com.entity.UserEntity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
// ApplicationContext
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
UserEntity userEntity = annotationConfigApplicationContext.getBean("userEntity", UserEntity.class);
annotationConfigApplicationContext.close();
}
}
其實判斷的方法還有很多種,比如
-
實作接口InitializingBean, DisposableBean
建立BookEntity.java
package com.entity;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class BookEntity implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("BookEntity 銷毀前執行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("BookEntity執行個體化完成");
}
}
2. JSR250
建立PayEntity.java
package com.entity;
import org.springframework.stereotype.Component;
@Component
public class PayEntity {
@PreDestroy
public void destroy(){
System.out.println("BookEntity 銷毀前執行");
}
@PostConstruct
public void afterPropertiesSet(){
System.out.println("BookEntity執行個體化完成");
}
}
弄清楚了怎麼判斷bean的初始化,我們先來看源碼
try中倒數第二個方法
可以看到上面的注釋,差不多意思為初始化所有的單例
初始化所有的單例,非懶加載
擷取所有的beanName,并使用RootBeanDefinition注入
上面幾步為查詢對象是否有初始化過,沒有的話就建立到IOC容器中
建立對象,判斷對象如果是單例的情況下調用該方法
建立IOC對象
通過反射執行個體化bean
populateBean(beanName, mbd, instanceWrapper);方法是給對象set方法屬性填充
initializeBean執行初始化方法(也可以自定義初始化方法)
判斷bean的類型是否Aware相關依賴,如果存在則回調方法
好了,重點來了
- 如果 Bean 實作了 BeanNameAware 接口,則 Spring 調用 Bean 的 setBeanName() 方法傳入目前 Bean 的 id 值。
- 如果 Bean 實作了 BeanFactoryAware 接口,則 Spring 調用 setBeanFactory() 方法傳入目前工廠執行個體的引用。
-
如果 Bean 實作了 ApplicationContextAware 接口,則 Spring 調用 setApplicationContext() 方法傳入目前 ApplicationContext 執行個體的引用。
第三點就完美解決了我們在過濾器當中,不能使用注解形式擷取bean的問題,我們可以直接通過上下文擷取bean。
好了,現在傳回到
初始化方法之前執行處理(增強)
2調用自定義init方法(使用java反射技術,此方法在無參構造函數後執行)
3在初始化方法之後調用(增強)
我們會發現1和3他們有一個單詞的差别,一個前一個後,也就是作用于自定義Init方法前後執行,在他們中間2也就是自定義Init方法
之後也就是調用,銷毀了。然後我們也就總結出了,bean生命周期的周期圖
語言描述:
Bean 生命周期的整個執行過程描述如下。
1)根據配置情況調用 Bean 構造方法或工廠方法執行個體化 Bean。
2)利用依賴注入完成 Bean 中所有屬性值的配置注入。
3)如果 Bean 實作了 BeanNameAware 接口,則 Spring 調用 Bean 的 setBeanName() 方法傳入目前 Bean 的 id 值。
4)如果 Bean 實作了 BeanFactoryAware 接口,則 Spring 調用 setBeanFactory() 方法傳入目前工廠執行個體的引用。
5)如果 Bean 實作了 ApplicationContextAware 接口,則 Spring 調用 setApplicationContext() 方法傳入目前 ApplicationContext 執行個體的引用。
6)如果 BeanPostProcessor 和 Bean 關聯,則 Spring 将調用該接口的預初始化方法 postProcessBeforeInitialzation() 對 Bean 進行加工操作,此處非常重要,Spring 的 AOP 就是利用它實作的。
7)如果 Bean 實作了 InitializingBean 接口,則 Spring 将調用 afterPropertiesSet() 方法。
8)如果在配置檔案中通過 init-method 屬性指定了初始化方法,則調用該初始化方法。
9)如果 BeanPostProcessor 和 Bean 關聯,則 Spring 将調用該接口的初始化方法 postProcessAfterInitialization()。此時,Bean 已經可以被應用系統使用了。
10)如果在 中指定了該 Bean 的作用範圍為 scope=“singleton”,則将該 Bean 放入 Spring IoC 的緩存池中,将觸發 Spring 對該 Bean 的生命周期管理;如果在 中指定了該 Bean 的作用範圍為 scope=“prototype”,則将該 Bean 交給調用者,調用者管理該 Bean 的生命周期,Spring 不再管理該 Bean。
11)如果 Bean 實作了 DisposableBean 接口,則 Spring 會調用 destory() 方法将 Spring 中的 Bean 銷毀;如果在配置檔案中通過 destory-method 屬性指定了 Bean 的銷毀方法,則 Spring 将調用該方法對 Bean 進行銷毀。
直至,還有一個重要的BeanPostProcessors,其實内部的重要方法我們已經見過
兩個處理器,當然,它遠遠沒有那麼簡單,後續揭曉