IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring基于注解扫描到创建BeanDefinition的原理 -> 正文阅读

[Java知识库]Spring基于注解扫描到创建BeanDefinition的原理

说明

本文以AnnotationConfigApplicationContext容器为例,来看看容器创建和扫描的过程,这里我们只主要介绍基于注解的扫描实现,如有不正确的地方欢迎指教。

前提知识

  • 子类容器依赖关系
    在这里插入图片描述
  • BeanFactoryPostProcessor原理

扫描准备阶段

创建容器对象

  1. 当创建容器对象时,我们会指定一个配置类,然后会调用构造方法,我们看看AnnotationConfigApplicationContext的构造方法内容如下
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
 		//该构造方法很重要,会初始注入一些默认的beanName
		this();
		//将传入的主类注册到容器中,该类一般有@Configuration(标记该类为配置类)、@ComponentScan(配置扫描的路径)
		register(componentClasses);
		//调用父类容器的刷新方法
		refresh();
}

public AnnotationConfigApplicationContext(String... basePackages) {
		this();
		//直接调用this()里面创建的scaner去完成扫描
		scan(basePackages);
		refresh();
}
  1. 上述构造方法干了很多事情,创建了AnnotatedBeanDefinitionReader(负责一些注入的功能)、ClassPathBeanDefinitionScanner(负责他自己的扫描功能,如当传入的是一个basePackage时)两个重要的类
public AnnotationConfigApplicationContext() {
		//该Reader的构造方法也很重要
		this.reader = new AnnotatedBeanDefinitionReader(this);
		//当调用String basePacket的构造方法时,会直接调用这个创建的scaner去完成扫描
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

注入spring内置类

  1. AnnotatedBeanDefinitionReader的构造方法,会像spring容器中注入一些内嵌的重要的类,注意此时注入的只是BeanDefinition对象,还未完成bean对象的创建。内容如下:
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		//该方法完成了很多内部类的注入
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
  1. 注入主要类的BeanDefinition如下:
  • ConfigurationClassPostProcessor该类就是本文完成后续扫描的重点类
  • AutowiredAnnotationBeanPostProcessor该类是BeanPostProcessor的子接口,是完成扫描@Autowired和@Value注解并创建对应的InjectionMetadata,完成自动注入的功能。具体内容可见Spring @Autowired源码解析不在本文的介绍范围之内。
  • CommonAnnotationBeanPostProcessor同上,主要是对@Resource注解的解析。
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}

		return beanDefs;
	}

  1. 类关系图如下
    在这里插入图片描述
  2. register(componentClasses)方法,指定了配置主类,并将该类定义为BeanDefinition注入到了容器中。

扫描阶段

调用refresh方法

  1. refresh方法中的invokeBeanFactoryPostProcessors(beanFactory);
/**
*
* 找到容器中所有的 实现了@see {@linkplain BeanDefinitionRegistryPostProcessor}
* 和@see {@linkplain BeanFactoryPostProcessor}的对象,
* 如系统默认提供的@see {@linkplain org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry)}
* 如 @see {@linkplain ConfigurationClassPostProcessor} 负责容器扫描的
*
* 并按照一定的顺序调用他们的方法,先按优先级调用 实现了BeanDefinitionRegistryPostProcessor接口的 {@linkplain BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
*
* 然后按优先级调用 @see {@linkplain org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
*
*/
invokeBeanFactoryPostProcessors(beanFactory);
  1. 先后三次调用org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法,每次调用之前都是从容器中获取BeanDefinitionRegistryPostProcessor.class类型的名称,然后调用getBean方法,该方法如果没有发现就会根据BeanDefinition去创建bean。后面还会调用BeanFactoryPostProcessor子类的postProcessBeanFactory方法,同样ConfigurationClassPostProcessor也实现了postProcessBeanFactory方法,它的方法会将Full属性的class进行增强。
  • 第一次是调用的上面准备阶段获取到的内置的BeanDefinitionRegistryPostProcessor实现类并且实现了PriorityOrdered即ConfigurationClassPostProcessor(该类的优先级是最高的,它实现了PriorityOrdered,设置的是LOWEST_PRECEDENCE = Integer.MAX_VALUE)的postProcessBeanDefinitionRegistry方法,该类会完成文件的扫描、创建对应的BeanDefinition,然后注入到容器的beanDefinitionMap中。当完成第一次默认的扫描后,用户有可能自己也定义了一些BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor的实现类。
  • 第二次继续从容器中获取BeanDefinitionRegistryPostProcessor.class类型并且实现了Ordered的名称,然后调用getBean方法,此时获取到的应该是用户自定义的BeanDefinitionRegistryPostProcessor实现类,然后调用他们的postProcessBeanDefinitionRegistry方法,进行自定义的功能,可完成自定义的扫描功能
  • 第三次调用没有实现Ordered接口的BeanDefinitionRegistryPostProcessor

解析配置主类

  1. 接下来介绍调用方法的具体逻辑
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		String[] candidateNames = registry.getBeanDefinitionNames();

		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				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
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		// 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) {
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}

		// Parse each @Configuration class
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			//具体解析的方法
			//该方法下ComponentScan注解负责的包下面的满足条件的bean会立即完成注册,而且会递归调用parse方法,
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				//创建reader对象进行load操作
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			//处理parse方法存入的BeanMethod、ImportedResources、ImportBeanDefinitionRegistrars的集合,并将它们注册到容器BeanDefinitionMap中
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses = new HashSet<>();
				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 && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}

		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
			// Clear cache in externally provided MetadataReaderFactory; this is a no-op
			// for a shared cache since it'll be cleared by the ApplicationContext.
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}
  1. 判断是否是配置类,加入到配置类候选集合中。然后调用ConfigurationClassParser的parse方法,该方法有对不同注解的处理逻辑,org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
  • 处理@PropertySource注解
  • 处理@ComponentScan注解
  • 处理@Import注解,它的ImportBeanDefinitionRegistrar实现类由ConfigurationClassBeanDefinitionReader处理
  • 处理@ImportResource注解,由ConfigurationClassBeanDefinitionReader在后面处理
  • 处理@Bean标注的methed,由ConfigurationClassBeanDefinitionReader在后面处理,即
this.reader.loadBeanDefinitions(configClasses);

代码如下:

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
				//立即执行扫描完成对beanDefinition的注册
				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();
					}
					//如果是Configuration注解的bean会递归调用parse方法
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// Process any @Import annotations
		//import注解的处理,包含普通的@Import注解、@Import+实现了ImportSelector的类、@Import+DeferredImportSelector
		//以及@Import+实现了ImportBeanDefinitionRegistrar的类
		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
		//解析@Bean注解的method,并放入beanMethed集合中
		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;
}

Component注解的解析

基础知识

@Service、@Repository、@Controller注解都是聚合了@Component注解的。

parse阶段

@Component主机的解析主要是通过org.springframework.context.annotation.ComponentScanAnnotationParser#parse方法完成的

  1. 创建ClassPathBeanDefinitionScanner
  2. 添加默认的includeFilter(ClassPathBeanDefinitionScanner的构造方法中调用)
protected void registerDefaultFilters() {
      //添加默认的includeFilter Component,后续就是根据这个去匹配的
   	this.includeFilters.add(new AnnotationTypeFilter(Component.class));
   	ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
   	try {
   		this.includeFilters.add(new AnnotationTypeFilter(
   				((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
   		logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
   	}
   	catch (ClassNotFoundException ex) {
   		// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
   	}
   	try {
   		this.includeFilters.add(new AnnotationTypeFilter(
   				((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
   		logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
   	}
   	catch (ClassNotFoundException ex) {
   		// JSR-330 API not available - simply skip.
   	}
   }
  1. 调用doScan
    org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
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) {
			//根据includeFilter集合去判断条件是否满足
			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);
				}
				//判断容器中是否已存在同名的beanDefinition,如果已存在会判断两个definition的source是否相同,如果相同则忽略,否则抛出异常
				//此处和
				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. 根据includeFilter创建候选的BeanDefinition集合
  • 获取对应basePacket包下面的所有class文件的Resource
  • 判断该class文件是否满足注入条件,即是否含有@Component注解
  • 注意上面过程并没有进行class文件的发射,而是根据文件流去获取对应class文件的MetadataReader对象,该对象就含有注解信息
  • 根据MetadataReader对象的注解信息和TypeFilter判断是否满足候选条件
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 {
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			//获取包下面的所有Resource文件
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			//遍历resource文件集合
			for (Resource resource : resources) {
				if (traceEnabled) {
					logger.trace("Scanning " + resource);
				}
				if (resource.isReadable()) {
					try {
						//根据resource获取MetadataReader(包含注解信息),根据流去获取ClassReader,不用反射实例化就可以获得对应
						//class文件的注解信息
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						/**
						 * 判断是否有@Compnent注解信息 @see {@link org.springframework.core.type.filter.AnnotationTypeFilter#matchSelf}
						 */
						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 (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;
}


protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
		for (TypeFilter tf : this.excludeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return false;
			}
		}
		for (TypeFilter tf : this.includeFilters) {
			//判断是否有@Compnent注解信息 @see {@linkplain org.springframework.core.type.filter.AnnotationTypeFilter#matchSelf}
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return isConditionMatch(metadataReader);
			}
		}
		return false;
}

parse解析后

  1. 创建ConfigurationClassBeanDefinitionReader对象
  2. 完成上面parse阶段放入到configClass里面的beanMethods、
    importedResources、importBeanDefinitionRegistrars集合的BeanDefinition对象的创建
private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();

private final Map<String, Class<? extends BeanDefinitionReader>> importedResources =
			new LinkedHashMap<>();

private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars =
			new LinkedHashMap<>();
private void loadBeanDefinitionsForConfigurationClass(
   		ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

   	if (trackedConditionEvaluator.shouldSkip(configClass)) {
   		String beanName = configClass.getBeanName();
   		if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
   			this.registry.removeBeanDefinition(beanName);
   		}
   		this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
   		return;
   	}

   	if (configClass.isImported()) {
   		registerBeanDefinitionForImportedConfigurationClass(configClass);
   	}
   	//parse阶段放入configClass的beanMethods
   	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
   		loadBeanDefinitionsForBeanMethod(beanMethod);
   	}
    //parse阶段放入configClass的importedResources
   	loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
   	//parse阶段放入configClass的importBeanDefinitionRegistrars
   	loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

至此,整个扫描class文件到满足条件的BeanDefinition创建和放入beanDefinitionMap中的过程就完成了。

自定义注解扫描及注入

其实自定义注解的扫描也很简单,可通过

  • 自定义注解
  • 实现BeanDefinitionRegistryPostProcessor类,并交给spring管理
  • 在对应实现方法中创建ClassPathBeanDefinitionScaner
  • 然后将自定义的注解加入到scaner的includeFilter集合
  • 最后调用scanner的scan方法就可以完成自定义注解的扫描和创建BeanDefination
    可对应参考mybatis和dubbo集成spring的扫描原理,学习他们是怎么完成自定义注解的扫描和注入过程
@Component
public class TestBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
   @Override
   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
   	ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry,false);
   	scanner.addIncludeFilter(new AnnotationTypeFilter(TestHuang.class));
   	scanner.scan("com.huangjie.custom");
   }

   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

   }
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-24 17:59:01  更:2022-05-24 18:01:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:06:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码