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;
}
}