5-Spring源码解析之this()(2)——ClassPathBeanDefinitionScanner

上一篇:4-Spring源码解析之this()(1)——AnnotatedBeanDefinitionReader
上一篇我们讲到

	private final AnnotatedBeanDefinitionReader reader;
	private final ClassPathBeanDefinitionScanner scanner;
	public AnnotationConfigApplicationContext() {
		// 步骤1:获取Spring7个内置处理器
		this.reader = new AnnotatedBeanDefinitionReader(this);
		// 步骤2:获取Spring的类扫描器Component
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

我们将this.reader = new AnnotatedBeanDefinitionReader(this);分析完后,reader得到了Spring的7个内置后置处理器。
那么下面,我们来分析第二步,获取Spring的类扫描器。我们进入ClassPathBeanDefinitionScanner类的构造器中。

1. ClassPathBeanDefinitionScanner类构造器

ClassPathBeanDefinitionScanner是一个从指定包内扫描所有Bean的Spring工具类。它在给定的包中进行扫描,找到其中标有注解且符合过滤规则的类,然后将这些类定义拿到将其注册到Spring容器中得到Bean组件。

在缺省的情况下,ClassPathBeanDefinitionScanner类只注册带有下面几个注解的类。

  • @Component
    • @Repository
    • @Service
    • @Controller
      • @RestController
  • @ManagedBean(Java EE 6)
  • @Named(JSR-330)
	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
		this(registry, true);
	}

	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
		this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
	}

	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment) {

		this(registry, useDefaultFilters, environment,
				(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
	}

	
	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, ResourceLoader resourceLoader) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		this.registry = registry;

		if (useDefaultFilters) {
			// 【1】
			registerDefaultFilters();
		}
		setEnvironment(environment);
		setResourceLoader(resourceLoader);
	}

我们可以看到上面一直在调用ClassPathBeanDefinitionScanner类的构造器,我们关注后面倒数第三个调用方法registerDefaultFilters()

2. registerDefaultFilters()

通过分析ClassPathBeanDefinitionScanner类中的方法可以直到,ClassPathBeanDefinitionScanner中并没有该方法,因此找到这个类的类结构。

在这里插入图片描述

发现它的父类ClassPathScanningCandidateComponentProvider类中有registerDefaultFilters()方法,我们进入该方法

	protected void registerDefaultFilters() {
		// 增加Component类,即注解过滤器类
		// 在上面我给出了注解的结构层级,因为Controoler、Service、Repotory注解都是Component的子注解,因此他们也可以起作用。
		this.includeFilters.add(new AnnotationTypeFilter(Component.class));
		ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
		try {
			// 添加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.
		}
	}

以上运行结束后我们this()方法就执行结束了。

3. 总结

  1. ClassPathBeanDefinitionScanner类的父类的registerDefaultFilters方法主要是给Spring容器中注册了注解过滤器类Component
  2. 实际上ClassPathBeanDefinitionScanner类的父类ClassPathScanningCandidateComponentProvider还有一个非常重要的方法:scan(),该方法才是真正进行包扫描的方法,但是因为文章的连续性,程序debug到哪里就叙述到哪里吧!

下一篇:6-Spring源码解析之register——register(annotatedClasses)注册配置类

发布了397 篇原创文章 · 获赞 71 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/xiaojie_570/article/details/104575049