衆所周知,在咱們平時的開發中,Spring這個框架已經環繞了整個項目,不是說咱們不能不用Spring,而是這樣作的代價太大了。每次面試,老是會問道Spring IOC、AOP、事務等等,今天這篇的話是猛男我剛工做碰到的一個面試真題,可憐我那時只知道@Service。而後就回去等通知了,到如今尚未給我通知。面試
另外的話,今天這篇會講幾種注入方式,至於原理好哥哥們就先別想了(別打我臉就行),這隨便拿一個出來都的講源碼講一遍,主要須要依賴的東西優勢多,因此找個機會將Spring IOC 那一塊的源碼弄出來講說,這一篇的話主要是講個大概。spring
這種方式就很簡單,像@Service、@Repository其實仍是用的@Component,在註解裏面點擊去看就知道了,須要注意的點是這種方式須要用@ComponentScan配置一個一個掃包範圍。爲何不用@Component這一個呢,主要是Spring爲了區分Bean的類型。@Repository做用於持久層,@Service 做用於業務邏輯層,@Controller做用於表現層(spring-mvc的註解)數組
@Componentpublic class ApproveCenterServiceImpl implements ApproveCenterService { }@Servicepublic class ApproveCenterServiceImpl implements ApproveCenterService { }@Repositorypublic class ApproveCenterServiceImpl implements ApproveCenterService { }複製代碼
這種方式是否是很熟悉,經常使用於標註配置類,最簡單的一個例子就是咱們使用SpringBoot 的時候須要手動註冊一個Bean``叫作RestTemplate`spring-mvc
@Configurationpublic class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate(); } }複製代碼
@Import 註解能夠註冊三種類型的Bean,第一種就是普通類,第二種DefinitionRegistrar類,第三種就是ImportSelectormvc
/** * @author xiejianwei */@Import(MessageRecord.class)public @interface ImportBean { }複製代碼
實現了ImportBeanDefinitionRegistrar,這種方式在實現類中提供了一個註冊器,有一個很熟悉的註解@MapperScan好哥哥們點進去看看就明白了。app
@Import(MapperScannerRegistrar.class)public @interface MapperScan { }public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { /** * 主要是這個方法,在參數中提供了BeanDefinitionRegistry這個註冊器,能夠手動向容器中注入bean */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AnnotationAttributes mapperScanAttrs = AnnotationAttributes .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));if (mapperScanAttrs != null) { registerBeanDefinitions(mapperScanAttrs, registry); } } }複製代碼
不少想Springboot starter中要開啓某個功能時就會用到ImportSelector,好比像開啓服務註冊與發現的註解@EnableDiscoveryClient,主要原理是ImportSelector中的selectImports方法會返回一個字符串的數組,這裏的字符串其實是一個個咱們須要註冊類的全路徑,相似於com.xjw.entity.pojo.MessageRecord,Spring會根據全路徑反射生成Bean。源碼這一塊就先不講了(手動狗頭)。框架
public class CommonModelSelector implements ImportSelector {public CommonModelSelector() { }public String[] selectImports(AnnotationMetadata annotationMetadata) {return new String[]{MessageRecord.class.getName()}; } }複製代碼
FactoryBean是一個特殊的Bean,是否不少好哥哥在面試時被問到過FactoryBean和BeanFactry的區別呢,說道這個個人眼眶溼潤了(講道理,這個在面所謂高級工程師的時候常常被問到)。FactoryBean是一個特殊Bean,當咱們實現這個接口時,會生成兩個Bean對象,第一個就是實現類自己,須要用在Bean名稱前(正常是類名首字母小寫)加&來獲取Bean,第二個Bean的話實際上就是getObject方法返回的bean,須要注意的是這種方式須要配合@Component或者@Configuration來實現。BeanFactry簡單點來講就是Spring上下文的容器。ide
實例代碼以下:rest
@Componentpublic class FactoryBeanLearn implements FactoryBean {@Overridepublic Object getObject() throws Exception {//這個Bean是咱們本身new的,這裏咱們就能夠控制Bean的建立過程了return new MessageRecord(); } /** * bean的類型 * **/@Overridepublic Class<?> getObjectType() {return MessageRecord.class; } /** * 是不是單例的 * **/@Overridepublic boolean isSingleton() {return true; } }複製代碼