1. 程式人生 > >SpringBoot的IOC模組註解及簡單案例(一)

SpringBoot的IOC模組註解及簡單案例(一)

本文將會講到SpringBoot的IOC模組下的註解進行總結,主要目的是為了方便之後查詢註解和快速應用。

將會以:元件註冊,生命週期,屬性賦值,自動裝配來進行區分。示例程式碼的註解很重要

一、元件註冊

1、@Configuration:標註在類上。主要是告訴 Spring 這是一個配置類。

//告訴 spring 這是一個配置類
@Configuration
public class MainConfig2 {

}

2、@ComponentScan:標註在類上。指定註解掃描的方式及範圍。

     FilterType.ANNOTATION               按註解      FilterType.ASSIGNABLE_TYPE    按給定的型別      FilterType.REGEX                          使用正則表示式      FilterType.CUSTOM                       自定義規則,必須實現 TypeFilter 這個介面

     1)、@excludeFilters = @Filter[ ],指定掃描按掃描規則 排除 哪些元件

@Configuration
@ComponentScan(value="com.duojia", excludeFilters = {
 		@Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
 		@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class}),
        @Filter(type = FilterType.CUSTOM, classes = MyTypeFilter.class)
})
public class MainConfig {
        // Controller 註解不掃描
        // BookService 類不掃描
        // MyTypeFilter 需要實現 TypeFilter 介面
}
public class MyTypeFilter implements TypeFilter {

	/**
	 * metadataReader,讀取當前類的掃描的類的資訊
	 * metadataReaderFactory,獲取到其他類的資訊
	 * return 返回值	false則不掃描,	ture則掃描
	 */
	public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
			throws IOException {
		// TODO Auto-generated method stub
		// 1.  獲取當前類註解的資訊
		AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		// 2. 獲取當前正掃描的類的資訊
		ClassMetadata classMetadata = metadataReader.getClassMetadata();
		// 3. 獲取當前類路徑
		Resource resource = metadataReader.getResource();
		// 4. 獲取當前註解類的類名
		String className = classMetadata.getClassName();
		
		System.out.println(" ----> " + className);
		
		return false;
	}

}

     2)、@includeFilters = @Filter[],指定掃描按掃描規則 包含 哪些元件

@ComponentScan(value="com.duojia", includeFilters = {
 		@Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
}, useDefaultFilters = false)
public class MainConfig {
        //只掃描 Controller 註解
        // useDefaultFilters 要設定為 false 才能讓 includeFilters 起效
}

3、@Bean:標註在方法上。指定需要裝載進 IOC 容器中的Bean

@Configuration
public class MainConfig2 {

        // 1. 給容器中註冊一個Bean;型別為返回值的型別,id預設是用方法名作為id
	// 2. 也可以在Bean括號裡面設定id
        @Bean("person")
	public Person person(){
		return new Person("張三", 20, "小三");
	}

}

4、@Scope:標註在方法上。指定 IOC 容器建立例項規則

@Configuration
public class MainConfig2 {

        /* 1. 預設是單例項,即容器中只有這一個例項,不管多次獲取,例項都是一個
	  2. 因此採用 Scope :
			prototype 多例項, ioc容器只有在獲取時,才會載入方法呼叫物件
			singleton 單例項, ioc容器在啟動時,就會載入方法呼叫物件
        */
        @Scope("pototype")
        @Bean
	public Person person(){
		return new Person("張三", 20, "小三");
	}

}

5、@Lazy:標註在方法上。懶載入,IOC 啟動時不會載入物件,只有在獲取時才會載入物件(與單例項一樣,只加載一次)

@Configuration
public class MainConfig2 {

        @Lazy
        @Bean
	public Person person(){
		return new Person("張三", 20, "小三");
	}

}

6、@Conditional:標註在類、方法上。在 spring 底層大量用到該註解,按照條件進行判斷,是否要註冊 Bean

@Configuration
public class MainConfig2 {

        /**
	 * @Conditional, 按照條件進行判斷,滿足條件給容器註冊bean
	 * 				傳入Condition陣列,且需實現 Condition(spring的Condition) 介面
	 */
	@Conditional({ConditionTest.class})
	@Bean("person2")
	public Person person2() {
		return new Person("Bob", 22, "b");
	}

}
public class ConditionTest implements Condition {

	
	/*
	 * ConditionContext: 上下文環境
	 * AnnotatedTypeMetadata: 註釋資訊
	 */
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
		// TODO Auto-generated method stub
		// 1. 能獲取到ioc使用的beanfactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		// 2. 獲取類載入器
		ClassLoader classLoader = context.getClassLoader();
		// 3. 獲取當前環境資訊
		Environment environment = context.getEnvironment();
		// 4. 獲取到bean定義的註冊類
		BeanDefinitionRegistry registry = context.getRegistry();
		
		
		return false;
	}

}

7、@Import:標註在方法上。快速給容器匯入一個元件。

方式:1)、@Import(要匯入到容器中的元件);容器中就會自動註冊這個元件,id預設是全類名            2)、ImportSelector:返回需要匯入的元件的全類名陣列,需要實現ImportSelector介面;            3)、ImportBeanDefinitionRegistrar:手動註冊bean到容器中。比上面一個可以自定義名

@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})	//快速匯入元件
public class MainConfig {

        //1. Color.class, Red.class 可以直接匯入
        //2. MyImportSelector.class 需要繼承 ImportSelector 介面
        //3. MyImportBeanDefinitionRegistrar.class 需要 繼承 ImportBeanDefinitionRegistrar 介面

}
//自定義邏輯,返回需要匯入的元件
public class MyImportSelector implements ImportSelector {

	//返回值就是要匯入到容器的元件全類名,不要返回null
	//AnnotationMetadata:當前標註@Import註解的類的資訊
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		// TODO Auto-generated method stub
		
		return new String[]{"com.duojia.bean.Yellow"};
	}

}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * AnnotationMetadata: 當前類的註解資訊
	 * BeanDefinitionRegistry: BeanDefinition註冊類,
	 * 			把所有需要註冊的Bean,手動註冊進來
	 */
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		// TODO Auto-generated method stub
		// 1. 容器類是否已經有名為Blue的類
		boolean bool = registry.containsBeanDefinition("com.duojia.bean.Blue");
		// 2. 沒有,就註冊進來
		if( !bool ) {
			//指定bean名
			RootBeanDefinition beanDefinition =  new RootBeanDefinition(Blue.class);
			registry.registerBeanDefinition("自定義Blue", beanDefinition);
		}
	}

}

8、(非註解)實現 FactoryBean 介面,可自定義工廠Bean

@Configuration
public class MainConfig2 {

        @Bean
	public ColorFactoryBean coloFactoryBean() {
		return new ColorFactoryBean();
	}
}
//建立一個Spring定義的FactoryBean(工廠Bean)
public class ColorFactoryBean implements FactoryBean<Color> {

	public Color getObject() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("建立一個Color");
		return new Color();
	}

	//設定Bean的型別
	//雖然定義的是FactoryBean,但實際上獲取的是Color
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return Color.class;
	}

	// 返回值:true	單例項
	//		 false	多例項
	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return false;
	}

}