ClassPathScanningCandidateComponentProvider 扫描给定包及其子包的类
生活随笔
收集整理的這篇文章主要介紹了
ClassPathScanningCandidateComponentProvider 扫描给定包及其子包的类
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
ClassPathScanningCandidateComponentProvider 類的findCandidateComponents()方法具體實現掃描給定類路徑包的功能,主要源碼如下:
//保存過濾規則要包含的注解,即Spring默認的@Component、@Repository、@Service、 //@Controller注解的Bean,以及JavaEE6的@ManagedBean和JSR-330的@Named注解 private final List<TypeFilter> includeFilters = new LinkedList<>();//保存過濾規則要排除的注解 private final List<TypeFilter> excludeFilters = new LinkedList<>(); //構造方法,該方法在子類ClassPathBeanDefinitionScanner的構造方法中被調用 public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters) {this(useDefaultFilters, new StandardEnvironment()); }public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) {//如果使用Spring默認的過濾規則,則向容器注冊過濾規則if (useDefaultFilters) {registerDefaultFilters();}setEnvironment(environment);setResourceLoader(null); } //向容器注冊過濾規則 @SuppressWarnings("unchecked") protected void registerDefaultFilters() {//向要包含的過濾規則中添加@Component注解類,注意Spring中@Repository//@Service和@Controller都是Component,因為這些注解都添加了@Component注解this.includeFilters.add(new AnnotationTypeFilter(Component.class));//獲取當前類的類加載器ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();try {//向要包含的過濾規則添加JavaEE6的@ManagedBean注解this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.}try {//向要包含的過濾規則添加@Named注解this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.} } //掃描給定類路徑的包 public Set<BeanDefinition> findCandidateComponents(String basePackage) {if (this.componentsIndex != null && indexSupportsIncludeFilters()) {return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);}else {return scanCandidateComponents(basePackage);} } private Set<BeanDefinition> addCandidateComponentsFromIndex(CandidateComponentsIndex index, String basePackage) {//創建存儲掃描到的類的集合Set<BeanDefinition> candidates = new LinkedHashSet<>();try {Set<String> types = new HashSet<>();for (TypeFilter filter : this.includeFilters) {String stereotype = extractStereotype(filter);if (stereotype == null) {throw new IllegalArgumentException("Failed to extract stereotype from "+ filter);}types.addAll(index.getCandidateTypes(basePackage, stereotype));}boolean traceEnabled = logger.isTraceEnabled();boolean debugEnabled = logger.isDebugEnabled();for (String type : types) {//為指定資源獲取元數據讀取器,元信息讀取器通過匯編(ASM)讀//取資源元信息MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(type);//如果掃描到的類符合容器配置的過濾規則if (isCandidateComponent(metadataReader)) {//通過匯編(ASM)讀取資源字節碼中的Bean定義元信息AnnotatedGenericBeanDefinition sbd = new AnnotatedGenericBeanDefinition(metadataReader.getAnnotationMetadata());if (isCandidateComponent(sbd)) {if (debugEnabled) {logger.debug("Using candidate component class from index: " + type);}candidates.add(sbd);}else {if (debugEnabled) {logger.debug("Ignored because not a concrete top-level class: " + type);}}}else {if (traceEnabled) {logger.trace("Ignored because matching an exclude filter: " + type);}}}}catch (IOException ex) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);}return candidates; } //判斷元信息讀取器讀取的類是否符合容器定義的注解過濾規則 protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {//如果讀取的類的注解在排除注解過濾規則中,返回falsefor (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return false;}}//如果讀取的類的注解在包含的注解的過濾規則中,則返回turefor (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return isConditionMatch(metadataReader);}}//如果讀取的類的注解既不在排除規則,也不在包含規則中,則返回falsereturn false; }?
總結
以上是生活随笔為你收集整理的ClassPathScanningCandidateComponentProvider 扫描给定包及其子包的类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ClassPathBeanDefinit
- 下一篇: 注册注解BeanDefinition