1、 @SpringBootApplication 注解中引用了@EnableAutoConfiguration 注解。
2、查看 @EnableAutoConfiguration 注解,發現引用了 @AutoConfigurationPackage 注解。
3、查看 @AutoConfigurationPackage 注解,引入了 Registrar.class 類,代碼如下:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import({Registrar.class}) public @interface AutoConfigurationPackage { String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; }
4、查看Registrar 類,發現Spring是通過 AutoConfigurationPackages.PackageImports 來封裝需要掃描的包路徑,繼續查看這個類的源碼,代碼如下:
private static final class PackageImports { private final List<String> packageNames; PackageImports(AnnotationMetadata metadata) { AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(AutoConfigurationPackage.class.getName(), false)); List<String> packageNames = new ArrayList(Arrays.asList(attributes.getStringArray("basePackages"))); Class[] var4 = attributes.getClassArray("basePackageClasses"); int var5 = var4.length; for(int var6 = 0; var6 < var5; ++var6) { Class<?> basePackageClass = var4[var6]; packageNames.add(basePackageClass.getPackage().getName()); } if (packageNames.isEmpty()) { packageNames.add(ClassUtils.getPackageName(metadata.getClassName())); } this.packageNames = Collections.unmodifiableList(packageNames); } List<String> getPackageNames() { return this.packageNames; } public boolean equals(Object obj) { return obj != null && this.getClass() == obj.getClass() ? this.packageNames.equals(((AutoConfigurationPackages.PackageImports)obj).packageNames) : false; } public int hashCode() { return this.packageNames.hashCode(); } public String toString() { return "Package Imports " + this.packageNames; } }
5、通過閱讀上面的源碼可以發現,如果我們沒有指定SpringBoot需要掃描的包路徑,默認通過 ClassUtils.getPackageName(metadata.getClassName()) 來獲取啟動類所在的包路徑,所以我們也可以通過Spring提供好的方法來獲取啟動類Application所在包的路徑了。