Spring框架学习[注解扫描和读取Bean](六)

2014-11-24 03:05:58 · 作者: · 浏览: 4
initionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder);
  • //向容器注册扫描到的Bean registerBeanDefinition(definitionHolder, this.registry);
  • } }
  • } return beanDefinitions;
  • } ……
  • }

    类路径Bean定义扫描器ClassPathBeanDefinitionScanner主要通过findCandidateComponents方法调用其父类ClassPathScanningCandidateComponentProvider类来扫描获取给定包及其子包下的类。

    (3).ClassPathScanningCandidateComponentProvider扫描给定包及其子包的类:

    ClassPathScanningCandidateComponentProvider类的findCandidateComponents方法具体实现扫描给定类路径包的功能,主要源码如下:

    [java] view plaincopy
    1. public class ClassPathScanningCandidateComponentProvider implements ResourceLoaderAware { //保存过滤规则要包含的注解,即Spring默认的@Component、@Repository、@Service、//@Controller注解的Bean,以及JavaEE6的@ManagedBean和JSR-330的@Named注解
    2. private final List includeFilters = new LinkedList (); //保存过滤规则要排除的注解
    3. private final List excludeFilters = new LinkedList (); //构造方法,该方法在子类ClassPathBeanDefinitionScanner的构造方法中被调用
    4. public ClassPathScanningCandidateComponentProvider(boolean useDefaultFilters) { //如果使用Spring默认的过滤规则,则向容器注册过滤规则
    5. if (useDefaultFilters) { registerDefaultFilters();
    6. } }
    7. //向容器注册过滤规则 protected void registerDefaultFilters() {
    8. //向要包含的过滤规则中添加@Component注解类,注意Spring中@Repository //@Service和@Controller都是Component,因为这些注解都添加了@Component注解
    9. this.includeFilters.add(new AnnotationTypeFilter(Component.class)); //获取当前类的类加载器
    10. ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try {
    11. //向要包含的过滤规则添加JavaEE6的@ManagedBean注解 this.includeFilters.add(new AnnotationTypeFilter(
    12. ((Class ) cl.loadClass(javax.annotation.ManagedBean)), false)); logger.info(JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning);
    13. } catch (ClassNotFoundException ex) {
    14. // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. }
    15. try { //向要包含的过滤规则添加@Named注解
    16. this.includeFilters.add(new AnnotationTypeFilter( ((Class ) cl.loadClass(javax.inject.Named)), false));
    17. logger.info(JSR-330 'javax.inject.Named' annotation found and supported for component scanning); }
    18. catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip.
    19. } }
    20. //扫描给定类路径的包 public Set findCandidateComponents(String basePackage) {
    21. //创建存储扫描到的类的集合 Set candidates = new LinkedHashSet ();
    22. try { //解析给定的包路径,this.resourcePattern=” **/*.class”,
    23. //ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX=“classpath:” //resolveBasePackage方法将包名中的”.”转换为文件系统的”/”
    24. String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + / + this.resourcePattern;
    25. //将给定的包路径解析为Spring资源对象 Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
    26. boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled();
    27. //遍历扫描到的资源 for (Resource resource : resources) {
    28. if (traceEnabled) { logger.trace(Scanning + resource);
    29. } if (resource.isReadable()) {
    30. try { //为指定资源获取元数据读取器,元信息读取器通过汇编(ASM)读//取资源元信息
    31. MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); //如果扫描到的类符合容器配置的过滤规则
    32. if (isCandidateComponent(metadataReader)) { //通过汇编(ASM)读取资源字节码中的Bean定义元信息
    33. ScannedGenericBeanDefinition sbd = n