Spring是怎样寻找类的

在Spring中写下这样的一段代码,Spring是怎样找到这个类的?

@Aspect
@Component
public class LoggerAspect {
}
ClassLoader可以加载类,但是却没有运行时API取出某个package下面的所有类。既然没有运行时API可以供调用,那么,Spring是怎样
找到这样的一个类,并读取它的注解?
前提:这里调查的问题是怎样遍历某一个包下的所有类,即一个包下有哪些类。
下面的代码就是Spring的找到classpath下的类的方法:
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
resolver.getResources("classpath*:org/springframework/core/io/support/**/*.class");
通过源码跟踪,发现Spring使用ClassLoader取出URL的枚举值,如下:
Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));
其中的path是org/springframework/core/io/support/
这个URL的格式如下:
jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.6.RELEASE/a1c6ef01f18888f51fc5054c65ef4787b7cf0a1e/spring-core-4.2.6.RELEASE.jar!/org/springframework/core/io/support/
这是一个jar文件,然后Spring会读取这个jar文件,然后遍历jar文件里的内容,进行路径的匹配,如下:
<pre name="code" class="html">...
if (con instanceof JarURLConnection) {
  // Should usually be the case for traditional JAR files.
  JarURLConnection jarCon = (JarURLConnection) con;
  ResourceUtils.useCachesIfNecessary(jarCon);
  jarFile = jarCon.getJarFile();
  jarFileUrl = jarCon.getJarFileURL().toExternalForm();
  JarEntry jarEntry = jarCon.getJarEntry();
  rootEntryPath = (jarEntry != null ? jarEntry.getName() : "");
}
...
Set<Resource> result = new LinkedHashSet<Resource>(8);
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
	JarEntry entry = entries.nextElement();
	String entryPath = entry.getName();
	if (entryPath.startsWith(rootEntryPath)) {
		String relativePath = entryPath.substring(rootEntryPath.length());
		if (getPathMatcher().match(subPattern, relativePath)) {
			result.add(rootDirResource.createRelative(relativePath));
		}
	}
}
...

再重复上面的过程,
 
1.首先使用ClassLoader取出哪些目录或jar文件包含参数路径,如下例:
目录:
0 = {UrlResource@7967} "URL [file:/Users/lvtu/buzhidaolvtu/boxfish-pay/pay-nami/build/classes/main/cn/boxfish/pay/]"
1 = {UrlResource@7968} "URL [file:/Users/lvtu/buzhidaolvtu/boxfish-pay/pay-common/build/classes/main/cn/boxfish/pay/]"
2 = {UrlResource@7969} "URL [file:/Users/lvtu/buzhidaolvtu/boxfish-pay/pay-api/build/classes/main/cn/boxfish/pay/]"
jar文件:
0 = {UrlResource@7552} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-devtools/1.3.5.RELEASE/ab035bdc1e6297ff4c8676edd93ed307b11353c2/spring-boot-devtools-1.3.5.RELEASE.jar!/org/springframework/]"
1 = {UrlResource@7553} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aspects/4.2.6.RELEASE/7ed7b15e95eedd551ac979bd8c295256d96cf2ff/spring-aspects-4.2.6.RELEASE.jar!/org/springframework/]"
2 = {UrlResource@7554} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework.security/spring-security-web/4.1.0.RELEASE/b0996431b0ebaa36794d1f2c81ecceaeb6ddece3/spring-security-web-4.1.0.RELEASE.jar!/org/springframework/]"
3 = {UrlResource@7555} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework.security/spring-security-config/4.1.0.RELEASE/98b549f97d9544c590ba656fb8a2d5ab369b410a/spring-security-config-4.1.0.RELEASE.jar!/org/springframework/]"
4 = {UrlResource@7556} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot/1.3.5.RELEASE/b218ba5f3bd01e657fbde9b085722da1fafa4f8a/spring-boot-1.3.5.RELEASE.jar!/org/springframework/]"
5 = {UrlResource@7557} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-autoconfigure/1.3.5.RELEASE/2bcfa86bb3afd95eff5252db6d78f2693b706997/spring-boot-autoconfigure-1.3.5.RELEASE.jar!/org/springframework/]"
6 = {UrlResource@7558} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.thymeleaf/thymeleaf-spring4/2.1.4.RELEASE/e5677e7daedfd05e001945abf4295305ac23826b/thymeleaf-spring4-2.1.4.RELEASE.jar!/org/springframework/]"
7 = {UrlResource@7559} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-actuator/1.3.5.RELEASE/97b25693835ca5bf436dea760fe337833d6aa51b/spring-boot-actuator-1.3.5.RELEASE.jar!/org/springframework/]"
8 = {UrlResource@7560} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-web/4.2.6.RELEASE/d5ce949da3f3266f118ed899a153413613b503ad/spring-web-4.2.6.RELEASE.jar!/org/springframework/]"
9 = {UrlResource@7561} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-webmvc/4.2.6.RELEASE/7c7ea475d33287e0e3a92e98ccbe0ad6a0dbb9ca/spring-webmvc-4.2.6.RELEASE.jar!/org/springframework/]"
10 = {UrlResource@7562} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework.security/spring-security-core/4.0.4.RELEASE/67e6eccc73a9887a7ca262c7cac20f9b36ce5a5d/spring-security-core-4.0.4.RELEASE.jar!/org/springframework/]"
11 = {UrlResource@7563} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/4.2.6.RELEASE/d4a319fb4d949fb6313f45c929947b9b4e26283e/spring-beans-4.2.6.RELEASE.jar!/org/springframework/]"
12 = {UrlResource@7564} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-context/4.2.6.RELEASE/bbf3c8526fe37bb341507f28db17882d4348dbca/spring-context-4.2.6.RELEASE.jar!/org/springframework/]"
13 = {UrlResource@7565} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/4.2.6.RELEASE/a1c6ef01f18888f51fc5054c65ef4787b7cf0a1e/spring-core-4.2.6.RELEASE.jar!/org/springframework/]"
14 = {UrlResource@7566} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-expression/4.2.6.RELEASE/c0182d73f348ab11d51d45cbe29f3820c32d0ccc/spring-expression-4.2.6.RELEASE.jar!/org/springframework/]"
15 = {UrlResource@7567} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aop/4.2.6.RELEASE/5efbfccb19efda2956b8977561bf4da6b15b0d0e/spring-aop-4.2.6.RELEASE.jar!/org/springframework/]"
16 = {UrlResource@7568} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jdbc/4.2.6.RELEASE/16075bfb0901a5b89c5be975365ff09b2df04abb/spring-jdbc-4.2.6.RELEASE.jar!/org/springframework/]"
17 = {UrlResource@7569} "URL [jar:file:/Users/lvtu/.gradle/caches/modules-2/files-2.1/org.springframework/spring-tx/4.2.6.RELEASE/ba7502c0644414748b1eeb65b4193b05d335a110/spring-tx-4.2.6.RELEASE.jar!/org/springframework/]"
2.遍历目录或jar文件,取出目录内的所有文件或jar文件内的所有文件
3.根据package筛选匹配的文件
4.找到了所有的class文件,也就是找到了所有的class类的全限定名。
5.Spring就可以根据这些全限定名加载类或使用类,通过容器管理这些类。

说明:有些步骤是猜测的,并没有追踪源代码。只是认为这样能实现就结束调查了。

以上是Spring的搜索类的方法。

下面的链接是JVM搜索类的方法:
https://docs.oracle.com/javase/8/docs/technotes/tools/findingclasses.html

jvm会根据classpath搜索class文件,然后加载该类。如果该文件存在多处,那么只有先被搜索到的文件才会被加载。





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值