1.扫描包路径下所有的类加载解析成bean定义信息
ClassPathBeanDefinitionScanner .doScan方法调用路径
doScan:276, ClassPathBeanDefinitionScanner (org.springframework.context.annotation)
parse:95, ComponentScanBeanDefinitionParser (org.springframework.context.annotation)
parse:76, NamespaceHandlerSupport (org.springframework.beans.factory.xml)
parseCustomElement:1475, BeanDefinitionParserDelegate (org.springframework.beans.factory.xml)
parseCustomElement:1452, BeanDefinitionParserDelegate (org.springframework.beans.factory.xml)
parseBeanDefinitions:181, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
doRegisterBeanDefinitions:150, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
registerBeanDefinitions:97, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)
registerBeanDefinitions:526, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
doLoadBeanDefinitions:397, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:341, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:310, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)
loadBeanDefinitions:190, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:234, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:197, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:267, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)
loadBeanDefinitions:150, AbstractXmlApplicationContext (org.springframework.context.support)
loadBeanDefinitions:102, AbstractXmlApplicationContext (org.springframework.context.support)
refreshBeanFactory:138, AbstractRefreshableApplicationContext (org.springframework.context.support)
obtainFreshBeanFactory:718, AbstractApplicationContext (org.springframework.context.support)
refresh:577, AbstractApplicationContext (org.springframework.context.support)
<init>:150, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:98, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:15, MyClassPathXmlApplicationContext (com.mashibing)
main:84, Test (com.mashibing)
parse:95, ComponentScanBeanDefinitionParser (org.springframework.context.annotation)
解析节点使用scanner在执行的basePackages包中执行扫描,返回已注册的bean定义
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 获取<context:component-scan>节点的base-package属性值
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);//base-package
// 解析占位符
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
// 解析base-package(允许通过,;\t\n中的任一符号填写多个)
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Actually scan for bean definitions and register them.
// 构建和配置ClassPathBeanDefinitionScanner
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);//类路径Bean定义扫描器
// 使用scanner在执行的basePackages包中执行扫描,返回已注册的bean定义
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
// 组件注册(包括注册一些内部的注解后置处理器,触发注册事件)
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
doScan:276, ClassPathBeanDefinitionScanner (org.springframework.context.annotation)
扫描开始
/**
* Perform a scan within the specified base packages, 在指定的基本包内执行扫描,
* returning the registered bean definitions. 返回已注册的bean定义。
* <p>This method does <i>not</i> register an annotation config processor 这个方法不注册注释配置处理器
* but rather leaves this up to the caller. 而是把这个问题留给调用者。
* @param basePackages the packages to check for annotated classes 要检查带注释的类的包
* @return set of beans registered if any for tooling registration purposes (never {@code null}) 为了工具注册目的而注册的bean集(从不{@code null})
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
// 遍历basePackages
for (String basePackage : basePackages) {
// 扫描basePackage,将符合要求的bean定义全部找出来
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 遍历所有候选的bean定义
for (BeanDefinition candidate : candidates) {
// 解析@Scope注解,包括scopeName和proxyMode
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 使用beanName生成器来生成beanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
// 处理beanDefinition对象,例如,此bean是否可以自动装配到其他bean中
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
// 处理定义在目标类上的通用注解,包括@Lazy,@Primary,@DependsOn,@Role,@Description
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 检查beanName是否已经注册过,如果注册过,检查是否兼容
if (checkCandidate(beanName, candidate)) {
// 将当前遍历bean的bean定义和beanName封装成BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 根据proxyMode的值,选择是否创建作用域代理
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册beanDefinition
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
// 扫描basePackage,将符合要求的bean定义全部找出来
Set candidates = findCandidateComponents(basePackage);
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
return scanCandidateComponents(basePackage);
}
}
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {//组装扫描路径(组装完成后是这种格式:classpath*:org/springframework/learn/demo01/**/*.class)
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);//根据路径获取资源对象,即扫描出该路径下的的所有class文件,得到 Resource
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {//根据资源对象获取资源对象的MetadataReader
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
if (isCandidateComponent(metadataReader)) {// 1. 是否需要初始化为spring bean,即是否有 @Component、@Service等注解//2. 查看配置类是否有@Conditional一系列的注解,然后是否满足注册Bean的条件
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);// 将 metadataReader 转换为 ScannedGenericBeanDefinition,这也是BeanDefinition家族中的一员
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 (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
判断是否可以生成bean定义信息
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
/**
* Determine whether the given class is a candidate component based on any 确定给定的类是否是基于任何的候选组件
* {@code @Conditional} annotations.{@code @Conditional}注释。
* @param metadataReader the ASM ClassReader for the class
* @return whether the class qualifies as a candidate component
*/
private boolean isConditionMatch(MetadataReader metadataReader) {
if (this.conditionEvaluator == null) {
this.conditionEvaluator =
new ConditionEvaluator(getRegistry(), this.environment, this.resourcePatternResolver);
}
return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata());
}
/**
* Determine if an item should be skipped based on {@code @Conditional} annotations.
* The {@link ConfigurationPhase} will be deduced from the type of item (i.e. a
* {@code @Configuration} class will be {@link ConfigurationPhase#PARSE_CONFIGURATION})
*
* @param metadata the meta data
* @return if the item should be skipped
*/
public boolean shouldSkip(AnnotatedTypeMetadata metadata) {
return shouldSkip(metadata, null);
}
/**
* 基于@Conditional标签判断该对象是否要跳过
* <p>
* Determine if an item should be skipped based on {@code @Conditional} annotations.
*
* @param metadata the meta data
* @param phase the phase of the call
* @return if the item should be skipped
*/
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
// metadata为空或者配置类中不存在@Conditional标签
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
// 采用递归的方式进行判断,第一次执行的时候phase为空,向下执行 // 判断传入的 phase
if (phase == null) {
// 下面的逻辑判断中,需要进入ConfigurationClassUtils.isConfigurationCandidate方法,主要的逻辑如下:
// 1、metadata是AnnotationMetadata类的一个实例
// 2、检查bean中是否使用@Configuration注解
// 3、检查bean不是一个接口
// 4、检查bean中是否包含@Component @ComponentScan @Import @ImportResource中任意一个
// 5、检查bean中是否有@Bean注解
// 只要满足其中1,2或者1,3或者1,4或者1,5就会继续递归
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
// 实例化 condition,其放入 conditions 中
List<Condition> conditions = new ArrayList<>();
for (String[] conditionClasses : getConditionClasses(metadata)) {// 1. getConditionClasses(metadata):获取 @Conditional 中指定的判断类
for (String conditionClass : conditionClasses) {
// 获取到@Conditional注解后面的value数组 // 2. 实例化操作(用到的还是反射),统一放到 conditions 中
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
// 对相关的条件进行排序操作
AnnotationAwareOrderComparator.sort(conditions);// 3. 排序上面得到的 condition 实例
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
// requiredPhase只可能是空或者是ConfigurationCondition的一个实例对象
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
//此逻辑为:1.requiredPhase不是ConfigurationCondition的实例
//2.phase==requiredPhase,从上述的递归可知:phase可为ConfigurationPhase.PARSE_CONFIGURATION或者ConfigurationPhase.REGISTER_BEAN
//3.condition.matches(this.context, metadata)返回false
//如果1、2或者1、3成立,则在此函数的上层将阻断bean注入Spring容器
return true;// 4. 调用 Condition#matches 方法进行判断
}
}
return false;
}
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata))
/**
* 检查给定的元数据,以查找给定的候选配置类是否被指定的注解标注
*
* Check the given metadata for a configuration class candidate
* (or nested component class declared within a configuration/component class).
* @param metadata the metadata of the annotated class
* @return {@code true} if the given class is to be registered for
* configuration class processing; {@code false} otherwise
*/
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
// Do not consider an interface or an annotation...
// 不考虑接口或注解
if (metadata.isInterface()) {
return false;
}
// Any of the typical annotations found?
// 检查是否被注解@Component、@ComponentScan、@Import、@ImportResource标注
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// Finally, let's look for @Bean methods...
// 最后检查是否有@Bean标注的方法
try {
return metadata.hasAnnotatedMethods(Bean.class.getName());
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
}
return false;
}
}