• invokeBeanFactoryPostProcessors


    一、唠嗑

    最近研究SpringBoot的源码,有了一个新的发现,这里把debug的整个过程先记录下来,只是记录过程,没有进行深入理解。或许有的人觉得没什么,你想想啊Spring最基础最牛逼的就是对bean的管理了,Spring所有的功能都是基于这个基础去扩展的。我这里找到了bean扫描和初始化的地方,这意味着如果研究透了这个过程和设计,对于Spring后面的理解就有基础了。哇哦..,这样你就可以很霸气的在简历上写上精通Spring,月薪过万都委屈你。

    二、源码流程

    1. ApplictionContext

    扫描并注入bean 在 refreshContext中。

    public ConfigurableApplicationContext run(String... args) {
    	long startTime = System.nanoTime();
    	DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    	ConfigurableApplicationContext context = null;
    	configureHeadlessProperty();
    	SpringApplicationRunListeners listeners = getRunListeners(args);
    	listeners.starting(bootstrapContext, this.mainApplicationClass);
    	try {
    		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    		ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
    		configureIgnoreBeanInfo(environment);
    		Banner printedBanner = printBanner(environment);
    		context = createApplicationContext();
    		context.setApplicationStartup(this.applicationStartup);
    		prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
    		// Spring 扫描到class并注入bean在这里面
    		refreshContext(context);
    		afterRefresh(context, applicationArguments);
    		Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
    		if (this.logStartupInfo) {
    			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
    		}
    		listeners.started(context, timeTakenToStartup);
    		callRunners(context, applicationArguments);
    	}
    	catch (Throwable ex) {
    		handleRunFailure(context, ex, listeners);
    		throw new IllegalStateException(ex);
    	}
    	try {
    		Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
    		listeners.ready(context, timeTakenToReady);
    	}
    	catch (Throwable ex) {
    		handleRunFailure(context, ex, null);
    		throw new IllegalStateException(ex);
    	}
    	return context;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    2. AbstractApplicationContext

    执行后置处理器 invokeBeanFactoryPostProcessors

    @Override
    public void refresh() throws BeansException, IllegalStateException {
    	synchronized (this.startupShutdownMonitor) {
    		StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    		prepareRefresh();
    		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    		prepareBeanFactory(beanFactory);
    		try {
    			postProcessBeanFactory(beanFactory);
    			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
    			// 看这里
    			invokeBeanFactoryPostProcessors(beanFactory);
    			registerBeanPostProcessors(beanFactory);
    			beanPostProcess.end();
    			initMessageSource();
    			initApplicationEventMulticaster();
    			onRefresh();
    			registerListeners();
    			finishBeanFactoryInitialization(beanFactory);
    			finishRefresh();
    		}
    
    		catch (BeansException ex) {
    			if (logger.isWarnEnabled()) {
    				logger.warn("Exception encountered during context initialization - " +
    						"cancelling refresh attempt: " + ex);
    			}
    			destroyBeans();
    			cancelRefresh(ex);
    			throw ex;
    		}
    
    		finally {
    			resetCommonCaches();
    			contextRefresh.end();
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    3. PostProcessorRegistrationDelegate

    继续进入到invokeBeanDefinitionRegistryPostProcessors,下面有很多这个方法,不过我已经在下面写注释了进行标识了。

    public static void invokeBeanFactoryPostProcessors(
    	ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    	Set<String> processedBeans = new HashSet<>();
    
    	if (beanFactory instanceof BeanDefinitionRegistry) {
    		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
    		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    
    		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
    			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
    				BeanDefinitionRegistryPostProcessor registryProcessor =
    						(BeanDefinitionRegistryPostProcessor) postProcessor;
    				registryProcessor.postProcessBeanDefinitionRegistry(registry);
    				registryProcessors.add(registryProcessor);
    			}
    			else {
    				regularPostProcessors.add(postProcessor);
    			}
    		}
    
    		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    		String[] postProcessorNames =
    				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    		for (String ppName : postProcessorNames) {
    			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    				processedBeans.add(ppName);
    			}
    		}
    		sortPostProcessors(currentRegistryProcessors, beanFactory);
    		registryProcessors.addAll(currentRegistryProcessors);
    		// 在这里
    		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    		currentRegistryProcessors.clear();
    
    		// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
    		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    		for (String ppName : postProcessorNames) {
    			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
    				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    				processedBeans.add(ppName);
    			}
    		}
    		sortPostProcessors(currentRegistryProcessors, beanFactory);
    		registryProcessors.addAll(currentRegistryProcessors);
    		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    		currentRegistryProcessors.clear();
    
    		// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
    		boolean reiterate = true;
    		while (reiterate) {
    			reiterate = false;
    			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    			for (String ppName : postProcessorNames) {
    				if (!processedBeans.contains(ppName)) {
    					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    					processedBeans.add(ppName);
    					reiterate = true;
    				}
    			}
    			sortPostProcessors(currentRegistryProcessors, beanFactory);
    			registryProcessors.addAll(currentRegistryProcessors);
    			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    			currentRegistryProcessors.clear();
    		}
    
    		// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
    		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    	}
    
    	else {
    		// Invoke factory processors registered with the context instance.
    		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    	}
    
    	// Do not initialize FactoryBeans here: We need to leave all regular beans
    	// uninitialized to let the bean factory post-processors apply to them!
    	String[] postProcessorNames =
    			beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    
    	// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    	// Ordered, and the rest.
    	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    	List<String> orderedPostProcessorNames = new ArrayList<>();
    	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    	for (String ppName : postProcessorNames) {
    		if (processedBeans.contains(ppName)) {
    			// skip - already processed in first phase above
    		}
    		else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    			priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    		}
    		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    			orderedPostProcessorNames.add(ppName);
    		}
    		else {
    			nonOrderedPostProcessorNames.add(ppName);
    		}
    	}
    
    	// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    
    	// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    	for (String postProcessorName : orderedPostProcessorNames) {
    		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    	}
    	sortPostProcessors(orderedPostProcessors, beanFactory);
    	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    
    	// Finally, invoke all other BeanFactoryPostProcessors.
    	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    	for (String postProcessorName : nonOrderedPostProcessorNames) {
    		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    	}
    	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    
    	// Clear cached merged bean definitions since the post-processors might have
    	// modified the original metadata, e.g. replacing placeholders in values...
    	beanFactory.clearMetadataCache();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    private static void invokeBeanDefinitionRegistryPostProcessors(
    	Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
    	for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
    		StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
    				.tag("postProcessor", postProcessor::toString);
    		// 这里
    		postProcessor.postProcessBeanDefinitionRegistry(registry);
    		postProcessBeanDefRegistry.end();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4. ConfigurationClassParser

    4.1 parse

    public void parse(Set<BeanDefinitionHolder> configCandidates) {
    	for (BeanDefinitionHolder holder : configCandidates) {
    		BeanDefinition bd = holder.getBeanDefinition();
    		try {
    			if (bd instanceof AnnotatedBeanDefinition) {
    				// 这里
    				parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
    			}
    			else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
    				parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
    			}
    			else {
    				parse(bd.getBeanClassName(), holder.getBeanName());
    			}
    		}
    		catch (BeanDefinitionStoreException ex) {
    			throw ex;
    		}
    		catch (Throwable ex) {
    			throw new BeanDefinitionStoreException(
    					"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
    		}
    	}
    
    	this.deferredImportSelectorHandler.process();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    4.2 parse

    protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
    	processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
    }
    
    • 1
    • 2
    • 3

    4.3 processConfigurationClass

    下面的方法就到了扫描bean的地方了,在do while循环里面,这段代码。

    protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
    	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
    		return;
    	}
    
    	ConfigurationClass existingClass = this.configurationClasses.get(configClass);
    	if (existingClass != null) {
    		if (configClass.isImported()) {
    			if (existingClass.isImported()) {
    				existingClass.mergeImportedBy(configClass);
    			}
    			// Otherwise ignore new imported config class; existing non-imported class overrides it.
    			return;
    		}
    		else {
    			// Explicit bean definition found, probably replacing an import.
    			// Let's remove the old one and go with the new one.
    			this.configurationClasses.remove(configClass);
    			this.knownSuperclasses.values().removeIf(configClass::equals);
    		}
    	}
    
    	// Recursively process the configuration class and its superclass hierarchy.
    	// 看这里。
    	SourceClass sourceClass = asSourceClass(configClass, filter);
    	do {
    		sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
    	}
    	while (sourceClass != null);
    
    	this.configurationClasses.put(configClass, configClass);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    4.4 SourceClass

    在下面这行代码,就是找到被 @Configuration @Componce @Controller … 注释的类。哇哦~~

    Set scannedBeanDefinitions =
    this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

    @Nullable
    protected final SourceClass doProcessConfigurationClass(
    		ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
    		throws IOException {
    
    	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    		// Recursively process any member (nested) classes first
    		processMemberClasses(configClass, sourceClass, filter);
    	}
    
    	// Process any @PropertySource annotations
    	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
    			sourceClass.getMetadata(), PropertySources.class,
    			org.springframework.context.annotation.PropertySource.class)) {
    		if (this.environment instanceof ConfigurableEnvironment) {
    			processPropertySource(propertySource);
    		}
    		else {
    			logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
    					"]. Reason: Environment must implement ConfigurableEnvironment");
    		}
    	}
    
    	// Process any @ComponentScan annotations
    	Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
    			sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    	if (!componentScans.isEmpty() &&
    			!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
    		for (AnnotationAttributes componentScan : componentScans) {
    			// The config class is annotated with @ComponentScan -> perform the scan immediately
    			// 这里啊
    			Set<BeanDefinitionHolder> scannedBeanDefinitions =
    					this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
    			// Check the set of scanned definitions for any further config classes and parse recursively if needed
    			for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
    				BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
    				if (bdCand == null) {
    					bdCand = holder.getBeanDefinition();
    				}
    				if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
    					parse(bdCand.getBeanClassName(), holder.getBeanName());
    				}
    			}
    		}
    	}
    
    	// Process any @Import annotations
    	processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
    
    	// Process any @ImportResource annotations
    	AnnotationAttributes importResource =
    			AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    	if (importResource != null) {
    		String[] resources = importResource.getStringArray("locations");
    		Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
    		for (String resource : resources) {
    			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
    			configClass.addImportedResource(resolvedResource, readerClass);
    		}
    	}
    
    	// Process individual @Bean methods
    	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    	for (MethodMetadata methodMetadata : beanMethods) {
    		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    	}
    
    	// Process default methods on interfaces
    	processInterfaces(configClass, sourceClass);
    
    	// Process superclass, if any
    	if (sourceClass.getMetadata().hasSuperClass()) {
    		String superclass = sourceClass.getMetadata().getSuperClassName();
    		if (superclass != null && !superclass.startsWith("java") &&
    				!this.knownSuperclasses.containsKey(superclass)) {
    			this.knownSuperclasses.put(superclass, configClass);
    			// Superclass found, return its annotation metadata and recurse
    			return sourceClass.getSuperClass();
    		}
    	}
    
    	// No superclass -> processing is complete
    	return null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    6. ComponentScanAnnotationParser

    6.1 parse

    最后一行

    return scanner.doScan(StringUtils.toStringArray(basePackages));

    public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, 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 includeFilterAttributes : componentScan.getAnnotationArray("includeFilters")) {
    		List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(includeFilterAttributes, this.environment,
    				this.resourceLoader, this.registry);
    		for (TypeFilter typeFilter : typeFilters) {
    			scanner.addIncludeFilter(typeFilter);
    		}
    	}
    	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);
    		}
    	}
    
    	boolean lazyInit = componentScan.getBoolean("lazyInit");
    	if (lazyInit) {
    		scanner.getBeanDefinitionDefaults().setLazyInit(true);
    	}
    
    	Set<String> basePackages = new LinkedHashSet<>();
    	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));
    	}
    
    	scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
    		@Override
    		protected boolean matchClassName(String className) {
    			return declaringClass.equals(className);
    		}
    	});
    	return scanner.doScan(StringUtils.toStringArray(basePackages));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    7. ClassPathBeanDefinitionScanner

    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);
    		for (BeanDefinition candidate : candidates) {
    			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
    			candidate.setScope(scopeMetadata.getScopeName());
    			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
    			if (candidate instanceof AbstractBeanDefinition) {
    				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
    			}
    			if (candidate instanceof AnnotatedBeanDefinition) {
    				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
    			}
    			if (checkCandidate(beanName, candidate)) {
    				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
    				definitionHolder =
    						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    				beanDefinitions.add(definitionHolder);
    				registerBeanDefinition(definitionHolder, this.registry);
    			}
    		}
    	}
    	return beanDefinitions;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    8. ClassPathScanningCandidateComponentProvider

    findCandidateComponents

    public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    	if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
    		return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
    	}
    	else {
    		return scanCandidateComponents(basePackage);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    scanCandidateComponents

    private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    	Set<BeanDefinition> candidates = new LinkedHashSet<>();
    	try {
    		String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
    				resolveBasePackage(basePackage) + '/' + this.resourcePattern;
    		Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
    		boolean traceEnabled = logger.isTraceEnabled();
    		boolean debugEnabled = logger.isDebugEnabled();
    		for (Resource resource : resources) {
    			if (traceEnabled) {
    				logger.trace("Scanning " + resource);
    			}
    			try {
    				MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
    				if (isCandidateComponent(metadataReader)) {
    					ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
    					sbd.setSource(resource);
    					if (isCandidateComponent(sbd)) {
    						if (debugEnabled) {
    							logger.debug("Identified candidate component class: " + resource);
    						}
    						candidates.add(sbd);
    					}
    					else {
    						if (debugEnabled) {
    							logger.debug("Ignored because not a concrete top-level class: " + resource);
    						}
    					}
    				}
    				else {
    					if (traceEnabled) {
    						logger.trace("Ignored because not matching any filter: " + resource);
    					}
    				}
    			}
    			catch (FileNotFoundException ex) {
    				if (traceEnabled) {
    					logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());
    				}
    			}
    			catch (Throwable ex) {
    				throw new BeanDefinitionStoreException(
    						"Failed to read candidate component class: " + resource, ex);
    			}
    		}
    	}
    	catch (IOException ex) {
    		throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    	}
    	return candidates;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    9. GeneriApplicationContext

    getResources

    最后一行return

    @Override
    public Resource[] getResources(String locationPattern) throws IOException {
    	if (this.resourceLoader instanceof ResourcePatternResolver) {
    		return ((ResourcePatternResolver) this.resourceLoader).getResources(locationPattern);
    	}
    	return super.getResources(locationPattern);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    10. AbstarctApplication

    10.1 getResources

    @Override
    public Resource[] getResources(String locationPattern) throws IOException {
    	return this.resourcePatternResolver.getResources(locationPattern);
    }
    
    • 1
    • 2
    • 3
    • 4

    11. PathMatchingResourcePatternResolver

    11.1 getResources

    findPathMatchingResources 下面有注释

    @Override
    public Resource[] getResources(String locationPattern) throws IOException {
    	Assert.notNull(locationPattern, "Location pattern must not be null");
    	if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
    		// a class path resource (multiple resources for same name possible)
    		if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
    			// a class path resource pattern
    			// 这里
    			return findPathMatchingResources(locationPattern);
    		}
    		else {
    			// all class path resources with the given name
    			return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
    		}
    	}
    	else {
    		// Generally only look for a pattern after a prefix here,
    		// and on Tomcat only after the "*/" separator for its "war:" protocol.
    		int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
    				locationPattern.indexOf(':') + 1);
    		if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
    			// a file pattern
    			return findPathMatchingResources(locationPattern);
    		}
    		else {
    			// a single resource with the given name
    			return new Resource[] {getResourceLoader().getResource(locationPattern)};
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    findPathMatchingResources

    到这里就差不多到底了,不过还有一层。

    protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
    	String rootDirPath = determineRootDir(locationPattern);
    	String subPattern = locationPattern.substring(rootDirPath.length());
    	Resource[] rootDirResources = getResources(rootDirPath);
    	Set<Resource> result = new LinkedHashSet<>(16);
    	for (Resource rootDirResource : rootDirResources) {
    		rootDirResource = resolveRootDirResource(rootDirResource);
    		URL rootDirUrl = rootDirResource.getURL();
    		if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith("bundle")) {
    			URL resolvedUrl = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirUrl);
    			if (resolvedUrl != null) {
    				rootDirUrl = resolvedUrl;
    			}
    			rootDirResource = new UrlResource(rootDirUrl);
    		}
    		if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
    			result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
    		}
    		else if (ResourceUtils.isJarURL(rootDirUrl) || isJarResource(rootDirResource)) {
    			result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern));
    		}
    		else {
    			result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
    		}
    	}
    	if (logger.isTraceEnabled()) {
    		logger.trace("Resolved location pattern [" + locationPattern + "] to resources " + result);
    	}
    	return result.toArray(new Resource[0]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    三、献上我的debug截图

    PathMatchingResourcePatternResolver类的findPathMatchingResources方法,完美对上。
    在这里插入图片描述

  • 相关阅读:
    【小月电子】安路国产FPGA开发板系统学习教程-LESSON6按键消抖
    原生微信小程序学习第一部分
    就想了解服务器为什么1M带宽网速却达不到1M
    RabbitMQ
    数据分析三剑客
    HC32_HC32F072FAUA_ADC内部温度传感器
    vue开发环境准备
    springBoot整合讯飞星火认知大模型
    [排序算法] 快速排序 (C++) (含三种写法)
    代码随想录算法训练营Day32 | 贪心算法(2/6) Leetcode 122.买卖股票的最佳时机 II 55. 跳跃游戏 45.跳跃游戏II
  • 原文地址:https://blog.csdn.net/qq_45716444/article/details/126684335