ComponentScanAnnotationParser

ComponentScan解析器

继承上一节所讲ComponentScan的解析器分为:
针对注解的ComponentScanAnnotationParser以及针对Application.xml配置文件中的context:component-scan的ComponentScanBeanDefinitionParser。

ComponentScanAnnotationParser

其中parser方法代码如下:

class ComponentScanAnnotationParser {

	private final Environment environment;

	private final ResourceLoader resourceLoader;

	private final BeanNameGenerator beanNameGenerator;

	private final BeanDefinitionRegistry registry;

	public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
				componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

		Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
		boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
		scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
				BeanUtils.instantiateClass(generatorClass));

		ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
		if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
			scanner.setScopedProxyMode(scopedProxyMode);
		}
		else {
			Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
			scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
		}

		scanner.setResourcePattern(componentScan.getString("resourcePattern"));

		for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addIncludeFilter(typeFilter);
			}
		}
		for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
			for (TypeFilter typeFilter : typeFiltersFor(filter)) {
				scanner.addExcludeFilter(typeFilter);
			}
		}

		boolean lazyInit = componentScan.getBoolean("lazyInit");
		if (lazyInit) {
			scanner.getBeanDefinitionDefaults().setLazyInit(true);
		}
		//这个是关键,通过componentScan.getStringArray("basePackages")获得componentScan注解
		//basePackagess属性的值,也就是需要扫描的包的路径。
		Set<String> basePackages = new LinkedHashSet<>();
		String[] basePackagesArray = componentScan.getStringArray("basePackages");
		for (String pkg : basePackagesArray) {
			//resolvePlaceholders说是用来解析占位符的
			//tokenizeToStringArray将字符串按照指定的字符转换成String[]数组,如字符串中不包含指		
			//定字符,则将整个字符串放进数组。如指定字符有多个,是分别按单个字符来切割的。 字符
			//串: “made,in;china” 指定字符:",;",返回数组:[made, in, china],这里CONFIG_LOCATION_DELIMITERS指的是"; \t\n"
			String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
					ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
			Collections.addAll(basePackages, tokenized);
		}
		//获取basePackageClasses,并且解析为类所在的包名,然后加入到basePackages
		for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
			basePackages.add(ClassUtils.getPackageName(clazz));
		}
		//如果在注解中没有指定basePackages属性,则默认为注解当前所在包
		if (basePackages.isEmpty()) {
			//getPackageName通过类的全限定名获得包名,比如
			//ClassUtils.getPackageName("org.springframework.util.ClassUtils")
			//=org.springframework.util
			basePackages.add(ClassUtils.getPackageName(declaringClass));
		}
		//添加过滤器
		scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
			@Override
			protected boolean matchClassName(String className) {
				return declaringClass.equals(className);
			}
		});
		//下面详细讲解
		return scanner.doScan(StringUtils.toStringArray(basePackages));
	}

}

显然,如果我们想要看懂这个源代码,就必须了解Environment ResourceLoader BeanNameGenerator BeanDefinitionRegistry ClassPathBeanDefinitionScanner AnnotationAttributes 等类;

AnnotationAttributes

请看

Environment

请看

ResourceLoader

请看

BeanNameGenerator

请看

BeanDefinitionRegistry

请看

ClassPathBeanDefinitionScanner.doScan

请看
非我本人所写,讲解很详细,值得浏览

BeanDefinition

请看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值