Spring Boot的出現極大的簡化了咱們的開發,讓咱們無需再寫繁雜的配置文件,其正是利用了註解的便捷性,而Spring Boot又依賴於Spring,所以深刻學習Spring的註解是十分必要的。java
寫在類上,聲明此類是一個配置類,替代xml文件正則表達式
做用:spring
給 IOC 容器中註冊一個Bean,通常添加在方法上,組件類型爲方法的返回值,id默認爲方法名稱數組
經常使用屬性:session
做用:app
根據自定義的規則,自動掃描 IOC 容器中全部組件,在 jdk1.8 以後能夠在一個類上定義多個@ComponentScan
。ide
還有一個@ComponentScans
註解,也能夠在裏面定義多個@ComponentScan
學習
經常使用屬性:測試
useDefaultFilters
屬性爲false如何使用FilterType.CUSTOM
自定義過濾規則?prototype
public class MyTypeFilter implements TypeFilter { /** * 匹配方法,肯定此過濾器是否與給定元數據描述的類匹配 * @param metadataReader 讀取到的當前正在掃描的類的信息 * @param metadataReaderFactory 能夠獲取到其餘任何類的信息 * @return true:匹配, false:不匹配 * @throws IOException */ @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //獲取當前類的註解信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //獲取當前正在掃描的類的信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); //獲取當前類資源(類的路勁) Resource resource = metadataReader.getResource(); //自定義匹配規則 String className = classMetadata.getClassName(); if(className.contains("Controller")){ return true; } return false; } }
做用:
調整做用域
經常使用參數:
懶加載,通常用於單例模式,容器啓動的時候不會建立bean,第一次調用的時候才建立
做用:
按照必定條件進行判斷,知足條件才註冊bean,能夠放在方法或類上,此註解在Spring Boot底層大量使用
經常使用參數:
做用:
給ioc容器中導入指定的組件
經常使用參數:
用法:
在配置類上添加以下形式的註解便可
@Import({Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
ImportSelector
傳入實現了 ImportSelector 接口的類,返回一個全類名數組,好處就是能夠自定義須要導入的組件
public class MyImportSelector implements ImportSelector { /** * 自定義導入的組件 * @param importingClassMetadata 當前標註了@Import註解的類的全部註解信息 * @return 返回全類名 */ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.spring.color.Blue", "com.spring.color.Yellow"}; } }
打斷點debug一下,能夠看到參數的信息,的確是當前標註@Import的類上的註解信息
ImportBeanDefinitionRegistrar
手動註冊bean到容器中,調用 registerBeanDefinition() 方法
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * * @param importingClassMetadata 當前標註了@Import註解的類的全部註解信息 * @param registry 容器中已註冊組件的信息 */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { int count = registry.getBeanDefinitionCount(); if(count > 10){ BeanDefinition beanDefinition = new RootBeanDefinition(Ten.class); registry.registerBeanDefinition("ten", beanDefinition); } } }
自定義一個類,實現 FactoryBean 接口
public class FoodFactoryBean implements FactoryBean<Food> { /** * 獲取實例對象 * @return * @throws Exception */ @Override public Food getObject() throws Exception { return new Food(); } /** * 獲取實例類型 * @return */ @Override public Class<?> getObjectType() { return Food.class; } /** * 是否單例,true:單例 false:多例 * @return */ @Override public boolean isSingleton() { return true; } }
使用@Bean註冊到容器
@Bean public FoodFactoryBean foodFactoryBean(){ return new FoodFactoryBean(); }
測試一下
@Test public void test2(){ Object bean = applicationContext.getBean("foodFactoryBean"); System.out.println("foodFactoryBean 的類型:" + bean.getClass()); }
運行結果以下,發現類型居然不是 FoodFactoryBean ,使用@Bean註冊的組件類型不是方法的返回值嗎?實際上,FoodFactoryBean註冊的時候調用的了 getObject() 方法,因此註冊的是 Food 類
foodFactoryBean 的類型:class com.spring.bean.Food
那麼若是想要得到 FoodFactoryBean 類怎麼辦呢?
看一下 BeanFactory 的源碼,定義了一個成員變量 FACTORY_BEAN_PREFIX
這個變量用於取消引用 FactoryBean 實例,並將其與由 FactoryBean 建立的bean區別開。
例如,若是名爲 test 的 bean 是 FactoryBean,則獲取 &test 將返回工廠,而不是工廠返回的實例。
因此在getBean的時候,在 id 前加上 & 便可
@Test public void test2(){ Object bean = applicationContext.getBean("&foodFactoryBean"); System.out.println("foodFactoryBean 的類型:" + bean.getClass()); }
註冊組件的方式: