ClassPathBeanDefinitionScanner 扫描给定的包及其子包
生活随笔
收集整理的這篇文章主要介紹了
ClassPathBeanDefinitionScanner 扫描给定的包及其子包
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
AnnotationConfigApplicationContext 通過調用類路徑Bean 定義掃描器ClassPathBeanDefinitionScanner 掃描給定包及其子包下的所有類,主要源碼如下:
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {private final BeanDefinitionRegistry registry;private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();@Nullableprivate String[] autowireCandidatePatterns;private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();private boolean includeAnnotationConfig = true;//創建一個類路徑Bean定義掃描器public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {this(registry, true);}//為容器創建一個類路徑Bean定義掃描器,并指定是否使用默認的掃描過濾規則。//即Spring默認掃描配置:@Component、@Repository、@Service、@Controller//注解的Bean,同時也支持JavaEE6的@ManagedBean和JSR-330的@Named注解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, @Nullable ResourceLoader resourceLoader) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");//為容器設置加載Bean定義的注冊器this.registry = registry;if (useDefaultFilters) {registerDefaultFilters();}setEnvironment(environment);//為容器設置資源加載器setResourceLoader(resourceLoader);}@Overridepublic final BeanDefinitionRegistry getRegistry() {return this.registry;}public void setBeanDefinitionDefaults(@Nullable BeanDefinitionDefaults beanDefinitionDefaults) {this.beanDefinitionDefaults =(beanDefinitionDefaults != null ? beanDefinitionDefaults : new BeanDefinitionDefaults());}public BeanDefinitionDefaults getBeanDefinitionDefaults() {return this.beanDefinitionDefaults;}public void setAutowireCandidatePatterns(@Nullable String... autowireCandidatePatterns) {this.autowireCandidatePatterns = autowireCandidatePatterns;}public void setBeanNameGenerator(@Nullable BeanNameGenerator beanNameGenerator) {this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator());}public void setScopeMetadataResolver(@Nullable ScopeMetadataResolver scopeMetadataResolver) {this.scopeMetadataResolver =(scopeMetadataResolver != null ? scopeMetadataResolver : new AnnotationScopeMetadataResolver());}public void setScopedProxyMode(ScopedProxyMode scopedProxyMode) {this.scopeMetadataResolver = new AnnotationScopeMetadataResolver(scopedProxyMode);}public void setIncludeAnnotationConfig(boolean includeAnnotationConfig) {this.includeAnnotationConfig = includeAnnotationConfig;}//調用類路徑Bean定義掃描器入口方法public int scan(String... basePackages) {//獲取容器中已經注冊的Bean個數int beanCountAtScanStart = this.registry.getBeanDefinitionCount();//啟動掃描器掃描給定包doScan(basePackages);// Register annotation config processors, if necessary.//注冊注解配置(Annotation config)處理器if (this.includeAnnotationConfig) {AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}//返回注冊的Bean個數return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);}//類路徑Bean定義掃描器掃描給定包及其子包protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");//創建一個集合,存放掃描到Bean定義的封裝類Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();//遍歷掃描所有給定的包for (String basePackage : basePackages) {//調用父類ClassPathScanningCandidateComponentProvider的方法//掃描給定類路徑,獲取符合條件的Bean定義Set<BeanDefinition> candidates = findCandidateComponents(basePackage);//遍歷掃描到的Beanfor (BeanDefinition candidate : candidates) {//獲取Bean定義類中@Scope注解的值,即獲取Bean的作用域ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);//為Bean設置注解配置的作用域candidate.setScope(scopeMetadata.getScopeName());//為Bean生成名稱String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);//如果掃描到的Bean不是Spring的注解Bean,則為Bean設置默認值,//設置Bean的自動依賴注入裝配屬性等if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}//如果掃描到的Bean是Spring的注解Bean,則處理其通用的Spring注解if (candidate instanceof AnnotatedBeanDefinition) {//處理注解Bean中通用的注解,在分析注解Bean定義類讀取器時已經分析過AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}//根據Bean名稱檢查指定的Bean是否需要在容器中注冊,或者在容器中沖突if (checkCandidate(beanName, candidate)) {BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);//根據注解中配置的作用域,為Bean應用相應的代理模式definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);//向容器注冊掃描到的BeanregisterBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;} }類路徑Bean 定義掃描器ClassPathBeanDefinitionScanner 主要通過findCandidateComponents()方法調用其父類ClassPathScanningCandidateComponentProvider 類來掃描獲取給定包及其子包下的類。
?
總結
以上是生活随笔為你收集整理的ClassPathBeanDefinitionScanner 扫描给定的包及其子包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 扫描指定包并解析为BeanDefinit
- 下一篇: ClassPathScanningCan