【Spring之ComponentScanAnnotationParser】

发布时间:2024年01月14日

1. ComponentScanAnnotationParser属性解析

	private final Environment environment;
	// 用于获取当前应用运行时的配置信息,包括但不限于系统属性、环境变量以及通过PropertySource添加
	// 的各种属性源。在处理@ComponentScan时,可能需要根据环境来决定哪些包或类应该被扫描。
	
	private final ResourceLoader resourceLoader;
	// spring资源加载器,用于加载不同类型的资源(如文件、类路径资源等)。在执行组件扫描时,可能需要
	// 加载指定包下面的所有类,这就需要用到ResourceLoader。

	private final BeanNameGenerator beanNameGenerator;
	// 一个策略接口实现,用于生成那些未明确提供名称的bean的默认名称。在扫描并创建bean的过程中,如
	//果没有未某个@Component或者@Service等注解的类显式设置beanName,则会用到此接口来生成唯一且有意	
	// 义的bean名称。

	private final BeanDefinitionRegistry registry;
	// SpringIOC容器的核心组件之一,它是所有BeanDefinition的注册表。ComponentScanAnnotationParser在
    // 解析过程中发现符合组件条件的类后,会将对应的BeanDefinition注册到这个BeanDefinitionRegistry中,
	// 使得这些类实例化后可以作为spring容器管理的bean进行依赖注入和生命周期管理。
	

2. 一个重要方法—parse

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
		// 创建类路径bean定义扫描
		ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
				componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
		// 获取nameGenerator
		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 {
		// 获取scope解决器
			Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
			// 设置scope解决器
			scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
		}
		// 设置资源模式
		scanner.setResourcePattern(componentScan.getString("resourcePattern"));
		// 添加用户自定义的incluedeFilter
		for (AnnotationAttributes includeFilterAttributes : componentScan.getAnnotationArray("includeFilters")) {
			List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(includeFilterAttributes, this.environment,
					this.resourceLoader, this.registry);
			for (TypeFilter typeFilter : typeFilters) {
				scanner.addIncludeFilter(typeFilter);
			}
		}
		// 添加用户自定义的excludeFilter
		for (AnnotationAttributes excludeFilterAttributes : componentScan.getAnnotationArray("excludeFilters")) {
			List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment,
				this.resourceLoader, this.registry);
			for (TypeFilter typeFilter : typeFilters) {
				scanner.addExcludeFilter(typeFilter);
			}
		}
		// 设置懒init
		boolean lazyInit = componentScan.getBoolean("lazyInit");
		if (lazyInit) {
			scanner.getBeanDefinitionDefaults().setLazyInit(true);
		}

		Set<String> basePackages = new LinkedHashSet<>();
		// 获取basePackages
		String[] basePackagesArray = componentScan.getStringArray("basePackages");
		for (String pkg : basePackagesArray) {
			String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
					ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
			Collections.addAll(basePackages, tokenized);
		}
		for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
			basePackages.add(ClassUtils.getPackageName(clazz));
		}
		// 如果为空, 则指定当前的配置类为基础包
		if (basePackages.isEmpty()) {
			basePackages.add(ClassUtils.getPackageName(declaringClass));
		}
		// 为了确保声明了@ComponentScan注解的类自身不会被扫描并注册为Bean。因为在大多数情况下,
		// 我们并不希望扫描器将包含@ComponentScan注解的类当作一个组件来处理。
		scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
			@Override
			protected boolean matchClassName(String className) {
				return declaringClass.equals(className);
			}
		});
		// 调用ClassPathBeanDefinitionScanner#doScan方法,返回Set<BeanDefinitionHolder>
		return scanner.doScan(StringUtils.toStringArray(basePackages));
	}
文章来源:https://blog.csdn.net/qq_39118371/article/details/135576393
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。