天天看點

全注解下的Spring IoC1. 引言2. 裝配Bean3. 依賴注入(Dependency Injection)4. 生命周期

文章目錄

  • 1. 引言
  • 2. 裝配Bean
    • 2.1 通過@Configuration方式
    • 2.2 通過@Component方式
  • 3. 依賴注入(Dependency Injection)
    • 3.1 消除歧義性——@Primary和@Qualifier
  • 4. 生命周期
    • 4.1 Bean定義過程
    • 4.2 Spring Bean生命周期

1. 引言

Spring最成功的是其提出的理念,而不是技術本身,他所依賴的兩個核心理念,一個是控制反轉(Inversion of Control,IoC),另一個是面向切面程式設計(Aspect Oriented Programming,AOP)。IoC容器是Spring的核心,可以說Spring是一個基于IoC容器程式設計的架構。

Spring Boot并不建議使用XML,而是通過注解的描述生成對象。Spring不僅要生成各種對象,同時還提供了依賴注入功能,使得我們可以通過描述來管理各個對象之間的關系。在Spring中把每一個需要管理的對象稱為Spring Bean(簡稱Bean),而Spring是管理這些Bean的容器,被我們稱為Spring IoC容器(簡稱IoC容器),IoC容器需要具備兩個基本功能:

  • 通過描述管理Bean,包括釋出和擷取Bean
  • 通過描述完成Bean之間的依賴關系
public interface BeanFactory {

	
	String FACTORY_BEAN_PREFIX = "&";

        //多個getBean的方法
	Object getBean(String name) throws BeansException;

	<T> T getBean(String name, Class<T> requiredType) throws BeansException;

	Object getBean(String name, Object... args) throws BeansException;

	<T> T getBean(Class<T> requiredType) throws BeansException;
	
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

	<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
	
	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
    
        //是否包含Bean
	boolean containsBean(String name);

        //是否單例模式
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	//是否原型模式
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	//是否類型比對
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
	
	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

        //擷取Bean的類型
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

	//擷取Bean的别名
	String[] getAliases(String name);

}
           

值得注意的是多個getBean()方法,這也是IoC容器最重要的方法之一,他的意義是從IoC容器中擷取Bean,他可以按類型或者名稱擷取Bean。

預設情況下Spring IoC容器的Bean都是以單例存在的,也就是用getBean()方法傳回的都是同一個對象,與isSingleton()方法相反的是isPrototype()方法,用來判斷是否為原型模式,如果傳回的是true,那麼使用getBean()方法傳回Bean的時候,Spring IoC容器就會建立一個新的Bean傳回給一個調用者。

為了進一步完善IoC容器的功能,在BeanFactory的基礎上,還設計了一個更為進階的子接口ApplicationContext。

2. 裝配Bean

2.1 通過@Configuration方式

@Configuration代表這是一個Java配置檔案,Spring容器會根據他來生成IoC容器去裝配Bean

@Bean(String name)會将被其注解的方法傳回的執行個體裝配到IoC容器中,name屬性定義這個Bean的名稱,預設與标準方法名相同。

2.2 通過@Component方式

Spring允許通過掃描裝配Bean到IoC容器中,對于掃描裝配而言使用的注解是@Component和@ComponentScan。@Component标明哪個類被掃描進入Spring IoC容器,而@ComponentScan則是标明采用何種政策去掃描裝配Bean。

@Component(String value)設定Bean的名稱,預設為類名首字母小寫。

@ComponentScan預設掃描目前注解類所在的包和子包,可以通過basePackages,basePackageClasses等修改掃描位置。

3. 依賴注入(Dependency Injection)

@Autowird是依賴注入中使用最多的注解之一,關于依賴注入這種設計模式的詳細解釋請至傳送門,他注入的機制最基本的一條是根據類型查找Bean,即BeanFactory接口中的

<T> T getBean(Class<T> requiredType) throws BeansException;
           

需要注意的是@Autowired是一個預設必須找到對應Bean的注解,如果不能确定其标注屬性一定存在,可以将required=false,他首先會根據類型查找Bean,如果對應的Bean不是唯一的,那麼他會根據屬性名稱和Bean的名稱進行比對。

3.1 消除歧義性——@Primary和@Qualifier

@Primary告訴Spring IoC容器發現多個同樣類型的Bean時,優先使用此注解的Bean

...
@Component
@Primary
public class demo{
	...
}
           

@Qualifier通過配置項value字元串定義需要的Bean name,與@Autowired組合使用,底層是通過BeanFactory借口的geatBean方法

<T> T getBean(String name,Class<T> requiredType) throws BeansException;
           

使用方法為

@Autowired
@Qualifier("name")
public ClassName instance = null;
           

4. 生命周期

Spring IoC管理Bean的生命周期大緻分為4個部分:

Bean定義、Bean初始化、Bean的生存期、Bean的銷毀。

4.1 Bean定義過程

Spring會通過配置比如@ComponentScan掃面帶有@Component注解的類定位資源,解析之後會将定義資訊儲存起來,然後将Bean定義釋出到IoC容器中,注意這個過程中隻有Bean的定義而沒有執行個體生成。

全注解下的Spring IoC1. 引言2. 裝配Bean3. 依賴注入(Dependency Injection)4. 生命周期

Spring 初始化Bean 可以通過設定@ComponentScan中的lazyInit來實作延遲加載,預設情況下為false在注入前已經執行個體化。

4.2 Spring Bean生命周期

全注解下的Spring IoC1. 引言2. 裝配Bean3. 依賴注入(Dependency Injection)4. 生命周期

這裡有幾個需要注意的地方:

接口BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean分别對應單個Bean的生命周期中的各個階段:定義,初始化和銷毀。而方法postProcessBeforeInitialization和postProcessAfterInitialization是接口BeanPostProcessor中的兩個方法,針對的是全部的Bean生效

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
	return bean;
    }
}
           

名為…Aware結尾的接口可以感覺到其前面的含義的變化并注入到Bean執行個體中,例如BeanNameAware便可以感覺到Bean的name并注入

public interface BeanNameAware extends Aware {
    void setBeanName(String name);
}
           

可以通過圖中的注解執行自定義的方法。