ConfigurationClassPostProcessor // BeanFactory後置處理器 postProcessBeanFactory // 上下文刷新時調用該方法 processConfigBeanDefinitions ConfigurationClassParser parse.parse(main.class) // Parse each @Configuration class
SpringBoot/SpringContext初始化加載過程可參考邏輯圖:
SpringApplication啓動過程
經過搜索「ConfigurationClassPostProcessor」找到對應節點java
ConfigurationClassParser parse processConfigurationClass // 遞歸地處理配置類及其超類層次結構 do { sourceClass = doProcessConfigurationClass { // 返回父類Class, 沒有則返回null processMemberClasses // 先遞歸地處理任何(嵌套)類 processPropertySource // 處理註解@PropertySource scannedBeanDefinitions = componentScanParser.parse // 處理註解@ComponentScan for(BeanDefinitionHolder holder : scannedBeanDefinitions) { parse(holder) // 遞歸 } processImports // 處理註解@Import configClass.addImportedResource // 處理註解@ImportResource configClass.addBeanMethod // 處理@Bean聲明的方法 processInterfaces // 處理接口上的默認方法 return sourceClass.getSuperClass // 返回父類給sourceClass } } while(sourceClass != null)
ComponentScanAnnotationParser componentScanParser.parse ClassPathBeanDefinitionScanner **scanner.doScan**
doScan調用
this.resourcePatternResolver.getResources(packageSearchPath)來所搜索指定包下所有的class
搜索路徑示例:classpath*:com/simple/boot/**/*.class
而後進行過濾, 組裝成一個個BeanDefinition後註冊到BeanFactory
// Dubbo中, 用於掃描DubboService com.alibaba.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner // MyBatis中, 用於掃描Mapper org.mybatis.spring.mapper.ClassPathMapperScanner
PathMatchingResourcePatternResolver#doFindAllClassPathResources
中調用ClassLoader#getResources("包路徑, 如: com/simple/"),ClassLoader爲Launcher$AppClassLoader, 結果示例:spring
result = 0 = "URL [file:/D:/simple-boot/target/classes/com/simple/]" 1 = "URL [jar:file:/D:/simple-boot/lib/simple-depend-1.0-SNAPSHOT.jar!/com/simple/]"
這樣會查出類路徑下, 全部符合包名前綴的rootDirURL, 而後循環Root路徑掃描子路徑mybatis
PathMatchingResourcePatternResolver#doFindPathMatchingFileResources
如問題1中, 根路徑URL [file:/D:/simple-boot/target/classes/com/simple/]
將匹配到該查詢方法
該方法遞歸目錄進行搜索app
PathMatchingResourcePatternResolver#doFindPathMatchingJarResources
如問題1中, 根路徑URL [jar:file:/D:/simple-boot/lib/simple-depend-1.0-SNAPSHOT.jar!/com/simple/]
將匹配到該查詢方法
將jar文件獲取或建立爲java.util.jar.JarFile
的實例, 經過Enumeration<JarEntry> entries = jarFile.entries()
方法循環全部文件post
PathMatchingResourcePatternResolver#getResources(String locationPattern)
中, 包名轉換成locationPattern的方式:this
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern;
假設basePackage="com.simple"
, 則將packageSearchPath會拼裝成classpath*:com/simple/**/*.class
spa