本文主要是介绍ClassPathBeanDefinitionScanner学习,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
简介
ClassPathBeanDefinitionScanner 是 Spring 框架中的一个类,它用于扫描类路径(classpath)上的组件并注册这些组件作为 Spring 容器中的 Bean。这个类通常用于实现基于 Java 配置的组件扫描,以及基于注解的自动配置。
ClassPathBeanDefinitionScanner 提供了一个简单的方法来扫描特定的包(package)以查找带有特定注解的类,并将这些类注册为 Spring 容器中的 Bean。这对于实现自动配置和简化 Spring 应用的配置非常有用。
以下是一些常用的 ClassPathBeanDefinitionScanner 方法:
- scan(String… basePackages): 扫描指定的包路径,并将找到的带有 @Component, @Service, @Repository, @Controller 等注解的类注册为 Bean。
- addIncludeFilter(TypeFilter filter): 添加一个过滤器,用于包含(即注册)符合特定条件的类。
- addExcludeFilter(TypeFilter filter): 添加一个过滤器,用于排除(即不注册)符合特定条件的类。
- findCandidateComponents(String basePackage): 在指定的包路径下查找候选的组件类。
源码
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {private final BeanDefinitionRegistry registry;private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();@Nullableprivate String[] autowireCandidatePatterns;//beanName生成器private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();//@Scope注解解析器private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();private boolean includeAnnotationConfig = true;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, @Nullable ResourceLoader resourceLoader) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");this.registry = registry;//是否使用默认的过滤器if (useDefaultFilters) {registerDefaultFilters();}//设置系统环境setEnvironment(environment);//设置资源加载器setResourceLoader(resourceLoader);}/*** Perform a scan within the specified base packages.* @param basePackages the packages to check for annotated classes* @return number of beans registered* 根据包路径进行扫描*/public int scan(String... basePackages) {//扫描之前的容器中已存在的bean的数量int beanCountAtScanStart = this.registry.getBeanDefinitionCount();//开始扫描doScan(basePackages);// Register annotation config processors, if necessary.if (this.includeAnnotationConfig) {AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}//返回新注册的bean的数量return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);}protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();for (String basePackage : basePackages) {//遍历所有包路径Set<BeanDefinition> candidates = findCandidateComponents(basePackage);//难道当前包下符合条件的所有BeanDefinitionfor (BeanDefinition candidate : candidates) {//设置bean的作用域ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);candidate.setScope(scopeMetadata.getScopeName());//获取bean的beanNameString beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);//设置AbstractBeanDefinition中的属性if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}if (candidate instanceof AnnotatedBeanDefinition) {AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}//校验当前bean是否重复加入容器中if (checkCandidate(beanName, candidate)) {//对bean进行包装BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);//判断当前bean是否需要代理,需要则创建代理对象并返回definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);//将bean注册到容器中registerBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;}/*** 向bean工厂中注册bean*/protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);}/***检查bean是否已经存在了*/protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {if (!this.registry.containsBeanDefinition(beanName)) {return true;}BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();if (originatingDef != null) {existingDef = originatingDef;}if (isCompatible(beanDefinition, existingDef)) {return false;}throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName +"' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " +"non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");}}
这篇关于ClassPathBeanDefinitionScanner学习的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!