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