1.进入方法ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
该方法的入口在refresh方法一步步调用遍历postProcessors的时候
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
/**
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
为什么把这个方法单独拿出来写,因为我觉得比较重要,首先值得注意的一点就是
ConfigurationClassPostProcessor他是实现了BeanDefinitionRegistryPostProcessor,而BeanDefinitionRegistryPostProcessor这个接口继承了BeanFactoryPostProcessor,所以他本身也是BeanFactoryPostProcessor,
在文章的开头说一下BeanFactoryPostProcessor和BeanPostProcessor的区别,BeanFactoryPostProcessor是针对BeanDefinition的,而BeanPostProcessor是针对Bean来来进行处理的,接下来我们继续看
这个方法首先判断是否调用过该方法
2.进入processConfigBeanDefinitions(registry);方法
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
@Override
public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
do {
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<String>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null) {
if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
该方法的入参就是beanFactory,这里是DefaultListableBeanFactory
3.String[] candidateNames = registry.getBeanDefinitionNames();
获取已经定义的beanDefinition的名称集合
[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, zongHeApplication, org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory]
值得注意的是这里有我们的启动类zongHeApplication的名称
接下来就是遍历
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
获取键对应的beanDefinition,这里是 RootBeanDefinition的实例
ConfigurationClassUtils.isFullConfigurationClass(beanDef)是判断该RootBeanDefinition是否是FullConfigurationClass
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)是判断该RootBeanDefinition是否是LIteConfigurationClass
ConfigurationClassUtils.checkConfigurationClassCandidate是判断该RootBeanDefinition是否是ConfigurationClassCandidate
直到遍历到zongHeApplication,ConfigurationClassUtils.checkConfigurationClassCandidate判断为true,而该beanDefinition也变成了AnnotedGenericBeanDefinition,下面是该类的简单描述
Generic bean: class [com.songhq.ZongHeApplication]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
满足条件则执行configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
循环遍历完成后,configCandidates只有zongHeApplication,下面是configCandidates进行排序
Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
@Override
public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
});
排序后执行,该小段代码是通过上下文发现自定义bean的生成策略
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
registry instanceof SingletonBeanRegistry判断该beanfactory时候是SingletonBeanRegistry类型,这里是,代表是单例工厂
判断上下文是否有单例名称为org.springframework.context.annotation.internalConfigurationBeanNameGenerator的对象,这里没有,应该就是代表没有自定义bean的生成规则
接下来就是 Parse each @Configuration class ,首先构造了一个ConfigurationClassParser对象,将上下文,环境,beanFactory都赋予了它
下面是关键方法parser.parse(candidates);
public void parse(Set<BeanDefinitionHolder> configCandidates) {
this.deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>();
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);
}
}
processDeferredImportSelectors();
}
进入parse方法
protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
进入processConfigurationClass
protected void processConfigurationClass(ConfigurationClass configClass) 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);
for (Iterator<ConfigurationClass> it = this.knownSuperclasses.values().iterator(); it.hasNext();) {
if (configClass.equals(it.next())) {
it.remove();
}
}
}
}
// Recursively process the configuration class and its superclass hierarchy.
SourceClass sourceClass = asSourceClass(configClass);
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
this.configurationClasses.put(configClass, configClass);
}
进入 asSourceClass该方法时Recursively process the configuration class and its superclass hierarchy
private SourceClass asSourceClass(ConfigurationClass configurationClass) throws IOException {
AnnotationMetadata metadata = configurationClass.getMetadata();
if (metadata instanceof StandardAnnotationMetadata) {
return asSourceClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
}
return asSourceClass(metadata.getClassName());
}
这里注意看metadata对象,这里用AnnotationMetadata接口接收,这里的使用的是StandardAnnotationMetadata,
该对象属性值annotations为[@org.springframework.boot.autoconfigure.SpringBootApplication(scanBasePackageClasses=[], excludeName=[], exclude=[], scanBasePackages=[]), @org.springframework.context.annotation.EnableAspectJAutoProxy(proxyTargetClass=true, exposeProxy=false)]
属性值introspectedClass为class com.songhq.ZongHeApplication
SourceClass是对com.songhq.ZongHeApplication的封装
最关键的地方在 这段代码,循环处理
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
进入doProcessConfigurationClass(configClass, sourceClass);
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
// Recursively process any member (nested) classes first
processMemberClasses(configClass, sourceClass);
// 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.warn("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) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
holder.getBeanDefinition(), this.metadataReaderFactory)) {
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
}
}
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
// Process any @ImportResource annotations
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
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.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;
}
首先,Recursively process any member (nested) classes first,即递归处理嵌套类
/**
* Register member (nested) classes that happen to be configuration classes themselves.
*/
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
for (SourceClass memberClass : sourceClass.getMemberClasses()) {
if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
if (this.importStack.contains(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
processConfigurationClass(memberClass.asConfigClass(configClass));
}
finally {
this.importStack.pop();
}
}
}
}
}
获取该Class or MetadataReader所依赖的类
public Collection<SourceClass> getMemberClasses() throws IOException {
Object sourceToProcess = this.source;
if (sourceToProcess instanceof Class) {
Class<?> sourceClass = (Class<?>) sourceToProcess;
try {
Class<?>[] declaredClasses = sourceClass.getDeclaredClasses();
List<SourceClass> members = new ArrayList<SourceClass>(declaredClasses.length);
for (Class<?> declaredClass : declaredClasses) {
members.add(asSourceClass(declaredClass));
}
return members;
}
catch (NoClassDefFoundError err) {
// getDeclaredClasses() failed because of non-resolvable dependencies
// -> fall back to ASM below
sourceToProcess = metadataReaderFactory.getMetadataReader(sourceClass.getName());
}
}
// ASM-based resolution - safe for non-resolvable classes as well
MetadataReader sourceReader = (MetadataReader) sourceToProcess;
String[] memberClassNames = sourceReader.getClassMetadata().getMemberClassNames();
List<SourceClass> members = new ArrayList<SourceClass>(memberClassNames.length);
for (String memberClassName : memberClassNames) {
try {
members.add(asSourceClass(memberClassName));
}
catch (IOException ex) {
// Let's skip it if it's not resolvable - we're just looking for candidates
if (logger.isDebugEnabled()) {
logger.debug("Failed to resolve member class [" + memberClassName +
"] - not considering it as a configuration class candidate");
}
}
}
return members;
}
Process any @PropertySource annotations,处理该类上的@PropertySource注解,这里没有直接跳过
接下来处理Process any @ComponentScan annotations,处理@ComponentScan,
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
这里的返回值为
[{value=[], basePackages=[], basePackageClasses=[], lazyInit=false, excludeFilters=[{type=CUSTOM, value=[class org.springframework.boot.context.TypeExcludeFilter], classes=[class org.springframework.boot.context.TypeExcludeFilter], pattern=[]}, {type=CUSTOM, value=[class org.springframework.boot.autoconfigure.AutoConfigurationExcludeFilter], classes=[class org.springframework.boot.autoconfigure.AutoConfigurationExcludeFilter], pattern=[]}], includeFilters=[], resourcePattern=**/*.class, useDefaultFilters=true, scopeResolver=class org.springframework.context.annotation.AnnotationScopeMetadataResolver, scopedProxy=DEFAULT, nameGenerator=interface org.springframework.beans.factory.support.BeanNameGenerator}]
这里能获取到值是因为@SpringBootApplication是组合注解,获取该注解后,进入了关键方法
// The config class is annotated with @ComponentScan -> perform the scan immediately
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
Assert.state(this.environment != null, "Environment must not be null");
Assert.state(this.resourceLoader != null, "ResourceLoader must not be null");
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);
}
Set<String> basePackages = new LinkedHashSet<String>();
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
basePackages.addAll(Arrays.asList(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));
}
上述方法在org.springframework.context.annotation.ComponentScanAnnotationParser类中
入参componentScan为AnnotationAtributes ,declaringClass 为com.songhq.ZongHeApplication
这里首先构造 ClassPathBeanDefinitionScanner scanner 这个对象,赋值一些解析时的参数
进入关键方法 scanner.doScan(StringUtils.toStringArray(basePackages));
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
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;
}
该方法在org.springframework.context.annotation.ClassPathBeanDefinitionScanner
接着进入关键方法Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
从方法名中就可以看出这个方法就是找到候选的组件,方法的入参为basePackage [com.songhq]
扫描包的时候会调用org.springframework.core.io.support.PathMatchingResourcePatternResolver类中findPathMatchingResources(String locationPattern)
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<Resource>(16);
for (Resource rootDirResource : rootDirResources) {
rootDirResource = resolveRootDirResource(rootDirResource);
URL rootDirURL = rootDirResource.getURL();
if (equinoxResolveMethod != null) {
if (rootDirURL.getProtocol().startsWith("bundle")) {
rootDirURL = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirURL);
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.isDebugEnabled()) {
logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);
}
return result.toArray(new Resource[result.size()]);
}
其中会打印日志 Resolved classpath location [com/songhq/] to resources [URL [file:/D:/songhaiqiang/code/workspace/my/zonghe/target/classes/com/songhq/]]
接着生成路径file:/D:/songhaiqiang/code/workspace/my/zonghe/target/classes/com/songhq/ URL对象
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);将所有的.class文件都获取到,这里获取到的是对应的文件的路径
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);就会根据文件路径解析出元数据,判断是否为组件的候选人
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return isConditionMatch(metadataReader);
}
}
return false;
}
当扫描到com.songhq.zonghe.controller.HttpsController这个的时候,判断回味true
ScannedGenericBeanDefinition 来封装解析到的.class文件,迭代之后扫描出所有符合条件的beanDefinition
接下来就是对这些beanDefinition进行处理,当然也是循环处理
这里以Generic bean: class [com.songhq.zonghe.controller.HttpsController]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [D:\songhaiqiang\code\workspace\my\zonghe\target\classes\com\songhq\zonghe\controller\HttpsController.class]
即HttpsController为例进行分析
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);解析该类的代理模式和是否为单例模式,用ScopeMetadata对象封装
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);生成bean的名称,这里为httpsController
循环一次后,就可以在beanFactory的beanDefinitionMap中看到已经多了一个键为httpsController的键值对
多次循环后就把基于ZhongHeApplication.calss扫描的beanDefinition都加载到beanDefinitionMap
下面这段代码就是递归检查扫描包
// Check the set of scanned definitions for any further config classes and parse recursively if needed
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
holder.getBeanDefinition(), this.metadataReaderFactory)) {
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
}
}
导致了对Process any @ComponentScan annotations的处理完毕,又到了上班的时间了
又到周末的时间了,又可以继续写了
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), true);
进入到了processImports方法
首先进入方法参数中的getImports(sourceClass)方法
/**
* Returns {@code @Import} class, considering all meta-annotations.
*/
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
Set<SourceClass> imports = new LinkedHashSet<SourceClass>();
Set<SourceClass> visited = new LinkedHashSet<SourceClass>();
collectImports(sourceClass, imports, visited);
return imports;
}
得到的imports如下[org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar, org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector, org.springframework.context.annotation.AspectJAutoProxyRegistrar]
其中EnableAutoConfigurationImportSelector是有以下配置出来的
@SpringBootApplication
—> @EnableAutoConfiguration
—> @Import(EnableAutoConfigurationImportSelector.class)
类似的其他两个也是一样,其中EnableAutoConfigurationImportSelector被弃用了
接着进入processImports方法
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) throws IOException {
if (importCandidates.isEmpty()) {
return;
}
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
this.deferredImportSelectors.add(
new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
对于不同类型的@Import采用不同的注入方式实现实例化,实例化的方法是
@SuppressWarnings("unchecked")
public static <T> T instantiateClass(Class<?> clazz, Class<T> assignableTo) throws BeanInstantiationException {
Assert.isAssignable(assignableTo, clazz);
return (T) instantiateClass(clazz);
}
public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
Assert.notNull(clazz, "Class must not be null");
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
return instantiateClass(clazz.getDeclaredConstructor());
}
catch (NoSuchMethodException ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
利用Class来反射进行实例化,接下来进行处理,这里不是很清楚这里有什么作用
下面执行了这些方法,注意在处理// Process any @ComponentScan annotations时候用到了递归,也就是下面这些处理过程符合条件的Component都会执行,递归就是最初进入的,最后跳出来,所以最后处理的是ZongHeApplication,跳出后,doProcessConfigurationClass方法才算执行完
// Process any @ImportResource annotations
// Process individual @Bean methods
// Process default methods on interfaces
// Process superclass, if any
// No superclass -> processing is complete
一步步返回到 parse(Set<BeanDefinitionHolder> configCandidates)方法,
接下来执行processDeferredImportSelectors();,处理延期的Import,我的理解是这些Import是有importSelectors生成的而不是有注解@Import直接生成的,所以取名deferred
private void processDeferredImportSelectors() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
for (DeferredImportSelectorHolder deferredImport : deferredImports) {
ConfigurationClass configClass = deferredImport.getConfigurationClass();
try {
String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
}
}
最终又会进入processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports)这个方法
注意的是这里的processConfigurationClass方法再进进入parse递归
回到主方法processConfigBeanDefinitions
接下来执行parser.validate();校验ConfigurationClass,这里的ConfigurationClass是由上面的ZhongHeApplication产生的bean的封装
构造一个对象 ConfigurationClassBeanDefinitionReader,解析set<ConfigurationClass>
this.reader.loadBeanDefinitions(configClasses);再次加载beanDefinition
再次注入一个特殊的实例化bean
Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
键为org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry
终于执行完毕
回到invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);的调用处
总结,该方法主要是用基于注解的方式解析启动类,把对应的beanDefinition注册到beanFactory,其中解析@ComponentScan
处有递归调用,这个递归处理了对beanDefinition的有哪些,相互依赖的是由processMemberClasses(configClass, sourceClass);
处理的,递归入口方法为processConfigurationClass(ConfigurationClass configClass);递归执行的主方法体就是
doProcessConfigurationClass(configClass, sourceClass);项目中的.class文件就是在次步骤中被读取的。