Spring注解源码解析:@Component

发布时间:2023-10-15 12:30

Spring注解源码解析:@Component

流程\"Spring注解源码解析:@Component_第1张图片\"

@Controller、@Service、@Repository的本质是@Component

注解
AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext(“XX.xx.xx”);
context.getBean();

1.AnnotationConfigApplicationContext

沿着AnnotationConfigApplicationContext的构造方法,看下Spring在源码层面又是如何处理标注了注解@Component的类:

	public AnnotationConfigApplicationContext(String... basePackages) {
		this();
    //扫描指定的bean
		scan(basePackages);
    //初始化容器
		refresh();
	}


方法this()中,初始化了两个成员变量this.reader和this.scanner,既然在构造方法中这么刻意的初始化它们,很有可能这两个成员变量的初始化逻辑中

可以看到首先会初始化BeanDefinitionRegistry类型的成员变量registr

beanDefinitionRegistry接口是Spring容器底层实现的一个接口,封装了注册BeanDefinition以及其他关于BeanDefinition相关的操作。

	public AnnotationConfigApplicationContext() {
    //注册一些注解的后置处理器
		this.reader = new AnnotatedBeanDefinitionReader(this);
    //指定要扫描的过滤
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

//看看AnnotatedBeanDefinitionReader 主要做什么的
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\");
    //初始化registry
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    //注册一些和注解相关的后置处理器BeanDefinition
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

AnnotationConfigUtils类中的方法registerAnnotationConfigProcessors

主要是注册一些类的BeanDefinition到Spring容器中 包括:

\"org.springframework.context.annotation.internalConfigurationAnnotationProcessor\";
\"org.springframework.context.annotation.internalAutowiredAnnotationProcessor\";
\"org.springframework.context.annotation.internalCommonAnnotationProcessor\";
\"org.springframework.context.annotation.internalPersistenceAnnotationProcessor\";
\"org.springframework.context.event.internalEventListenerProcessor\";
\"org.springframework.context.event.internalEventListenerFactory\";

beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));

另外一个成员变量也就是this.scanner对应的ClassPathBeanDefinitionScanner的初始化:

设置环境变量组件environment及相应的资源加载器resourceLoader,最终我们还是看到了一些重要的逻辑,如方法registerDefaultFilters

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
		this(registry, true);
	}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
		this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
	}

	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {

		Assert.notNull(registry, \"BeanDefinitionRegistry must not be null\");
		this.registry = registry;

		if (useDefaultFilters) {
			registerDefaultFilters();
		}
		setEnvironment(environment);
		setResourceLoader(resourceLoader);
	}

​ registerDefaultFilters();

在方法registerDefaultFilters中,我们发现主要就是往集合includeFilters中注册一些AnnotationTypeFilter,而通过AnnotationTypeFilter的名称,我们大概可以知道这是一个注解过滤器,是用来过滤指定类型的注解的。

protected void registerDefaultFilters() {
  //注册Component类型的注解过滤器
		this.includeFilters.add(new AnnotationTypeFilter(Component.class));
		ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
		try {
      //注册javax.annotation.ManagedBean
			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 {
      //注册avax.inject.Named\"
			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.
		}
	}

2.Scan();

Spring接下来会把扫描的任务委托给成员变量this.scanner处理,而this.scanner刚刚我们也看到了它的初始化,实际类型为ClassPathBeanDefinitionScanner。

@Override
public void scan(String... basePackages) {
   Assert.notEmpty(basePackages, \"At least one base package must be specified\");
   this.scanner.scan(basePackages);
}

首先通过成员变量this.registry的方法getBeanDefinitionCount,获取Spring容器当前已经注册BeanDefinition的个数。

然后在方法最后,用当前Spring容器中BeanDefinition的数量,减去初始Spring容器中BeanDefinition数量,得到本次方法执行时一共注册了多少个BeanDefinition。

	public int scan(String... basePackages) {
		int beanCountAtScanStart = this.registry.getBeanDefinitionCount();

		doScan(basePackages);

		// Register annotation config processors, if necessary.
		if (this.includeAnnotationConfig) {
			AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
		}

		return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
	}

doScan(basePackages);

方法doScan会遍历所有包路径,依次到这些包路径下扫描并加载BeanDefinition,

	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) {
      //在包路径下,加载符合条件的beanDefinitions
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
        //获取beanDefinitions的 注解@Scope的元数据信息
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
        //设置beanDefinitions的作用域为单例
				candidate.setScope(scopeMetadata.getScopeName());
        //生成bean的名称
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
          //为beanDefinitions注册一些默认的属性值
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
          //为其他各种注解上的信息,设置在beanDefinitions
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
        //判断当前的candiate,和容器中已经注册的beanDefinitions是否兼容
				if (checkCandidate(beanName, candidate)) {
          //将beanDefinitions和beanName封装到BeanDefinitionHolder
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
          //注册BeanDefinitionHolder在spring容器中
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

findCandidateComponents()

方法scanCandidateComponents果然开始扫描指定路径下的类了,首先会对我们传进去的包路径basePackage进行一些拼接处理,其中,ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX的值为“classpath*”,this.resourcePattern默认值为“**/*.class”。

再加上我们设置的basePackage值为“com.x x x.container.annotation.component”,所以,我们可以很容易的得到packageSearchPath的值为:classpath*:com.xxx.container.annotation.component/**/*.class,也就是扫描该路径下的所有类,每个类我们都可以得到相应的资源Resource。

	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[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			boolean traceEnabled = logger.isTraceEnabled();
			boolean debugEnabled = logger.isDebugEnabled();
			for (Resource resource : resources) {
				if (resource.isReadable()) {
					try {
            //将resource封装到MetadataReader中,MetadataReader为资源Resource访问组件
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
            //判断当前的Resouce是否符合条件
						if (isCandidateComponent(metadataReader)) {
              //metadataReader封装到ScannedGenericBeanDefinition 类型的BeanDefinition
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setSource(resource);
              //判断ScannedGenericBeanDefinition当前的属否符合条件
							if (isCandidateComponent(sbd)) {
								if (debugEnabled) {
									logger.debug(\"Identified candidate component class: \" + resource);
								}
								candidates.add(sbd);
							}
		}
		return candidates;
	}

isCandidateComponent()

Spring是通过注解过滤器来过滤资源的,可以看到方法中会通过封装了注解过滤器的集合this.includeFilters,来过滤封装了Resource的MetadataReader。

因为this.includeFilter中添加了注解@Component的过滤器,所以,这里只会将标注了@Component注解的类给留下来,而成员变量this.excludeFilters很明显也是用来存放注解的过滤器,只不过它存放的注解过滤器,是用来剔除掉指定类型的注解过滤器的。

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;
	}

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号