Spring源码解析(二):bean容器的创建、默认后置处理器、扫描包路径bean

有时候,不是因为你没有能力,也不是因为你缺少勇气,只是因为你付出的努力还太少,所以,成功便不会走向你。而你所需要做的,就是坚定你的梦想,你的目标,你的未来,然后以不达目的誓不罢休的那股劲,去付出你的努力,成功就会慢慢向你靠近。

导读:本篇文章讲解 Spring源码解析(二):bean容器的创建、默认后置处理器、扫描包路径bean,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

Spring源码系列文章

Spring源码解析(一):环境搭建

Spring源码解析(二):


一、Spring源码基础组件

  • 阅读源码时候,接口与类过多,可以对照这里查看对应的关系

1、bean定义接口体系

在这里插入图片描述

2、bean工厂接口体系

在这里插入图片描述

3、ApplicationContext上下文体系

在这里插入图片描述

二、AnnotationConfigApplicationContext注解容器

配置类:

@ComponentScan("com.xc")
@Configuration
public class Config {
    @Bean()
    public Book book(){
        return new Book();
    }
}

启动类:

public class Client {
    public static void main(String[] args) {
        //创建注解容器,入参为配置类
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        //获取某个bean
        Book book = context.getBean(Book.class);
        System.out.println(book);
        //关闭容器
        context.close();
    }
}

AnnotationConfigApplicationContext的构造方法:

在这里插入图片描述

1、创建bean工厂-beanFactory

  • 调用AnnotationConfigApplicationContext 的无参构造方法

在这里插入图片描述

  • AnnotationConfigApplicationContext的父类是GenericApplicationContext
  • 调用当前类的无参构造,先会调用父类的无参构造,先看下父类无参构造做的事情
  • 这个beanFactory就是spring容器的核心实现类

在这里插入图片描述

  • DefaultListableBeanFactory(bean容器)会存放bean定义及bean名称集合等等

在这里插入图片描述

  • DefaultListableBeanFactory父类DefaultSingletonBeanRegistry会缓存所有实例化的bean

在这里插入图片描述

  • 接下来继续查看AnnotatedBeanDefinitionReaderClassPathBeanDefinitionScanner的创建

2、注册默认后置处理器

  • 调用AnnotatedBeanDefinitionReader的有参构造方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 注册默认后置处理器
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
		BeanDefinitionRegistry registry, @Nullable Object source) {
	// 1.获取之前创建好的DefaultListableBeanFactory对象,beanFactory实例
	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	// 2.为beanFactory添加两属性
	if (beanFactory != null) {
		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
			beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
		}
		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
		}
	}
	// 3.bean定义持有集合(持有bean定义、名字、别名)
	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
	// 查询beanDefinitionMap是否有 internalConfigurationAnnotationProcessor = ConfigurationClassPostProcessor
	// 3.1.注册@Configuration,@Import,@ComponentScan,@Bean等注解 bean定义后置处理器
	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
		// 注册到beanDefinitionMap中,并添加到beanDefs集合中
		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	// 注册AutowiredAnnotationBeanPostProcessor
	// 3.2.注册@Autowired注解 bean后置处理器
	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));
	}

	// JSR-250,是java定义的一些注解,spring支持这注解。大致有:@PostConstruct @PreDestroy @Resource
	// 3.3.注册@Resource @PostConstruct @PreDestroy注解 bean后置处理器
	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));
	}

	// 3.4.spring注册支持jpa注解的beanFactory后置处理器
	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));
	}
	// 3.5.注册事件监听后置处理器 EventListenerMethodProcessor
	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));
	}
	// 3.6.注册事件监听工厂 DefaultEventListenerFactory
	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;
}
  • 查看一共注册的beanDefinition

在这里插入图片描述

  1. internalConfigurationAnnotationProcessor = ConfigurationClassPostProcessor
    • @Configuration,@Import,@ComponentScan,@Bean等注解 bean定义后置处理器
  2. internalAutowiredAnnotationProcessor = AutowiredAnnotationBeanPostProcessor
    • @Autowired注解 bean实例化后置处理器
  3. internalCommonAnnotationProcessor = CommonAnnotationBeanPostProcessor
    • @Resource @PostConstruct @PreDestroy注解 bean实例化后置处理器
  4. internalEventListenerProcessor = EventListenerMethodProcessor 事件监听后置处理器
  5. internalEventListenerFactory = DefaultEventListenerFactory 事件监听工厂

3、自定义扫描包功能

  • 调用ClassPathBeanDefinitionScanner的有参构造方法
protected void registerDefaultFilters() {
	// 注册过滤器 添加 @Component
	// @Controller @Service @Repository 也会被扫描
	this.includeFilters.add(new AnnotationTypeFilter(Component.class));
	ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
	try {
		// 扫描 JSR-250 @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 {
		//扫描 JSR-330 @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.
	}
}
  • 注册扫描过滤器 @Component,@Controller 、@Service、 @Repository 也会被添加进去
  • ClassPathBeanDefinitionScanner类:主要为了扩展AnnotationConfigApplicationContext添加一个自助扫描包的功能
  • 配置类上@ComponentScan注解扫描包路径下bean也是由此类实现
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
context.scan("com.xc.entity");

查看扫描包的源码

  • 这个方法主要就是进行扫描包路径,然后得到一个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) {
		// 扫描得到beanDefinition,主要进行行excludeFilters、includeFilters判断和Conditional判断
		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
		// 遍历BeanDefinition
		for (BeanDefinition candidate : candidates) {
			// 解析scope注解信息
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			// 设置scope注解信息
			candidate.setScope(scopeMetadata.getScopeName());
			// 主要是解析Component有没有设置bean的名字,有则直接返回
			// 没有则根据短名构造一个(如果写的名字第1、2个字符是大写则直接返回,否则直接将第一个字符转成小写返回)
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			if (candidate instanceof AbstractBeanDefinition) {
				// 主要是给BeanDefinition设置一些默认的值
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			if (candidate instanceof AnnotatedBeanDefinition) {
				// 获取类上的@Lazy、@Primary、@DependsOn、@Role、@Description相关信息并设置到定义信息中
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			// 检查Spring容器中是否已经存在该beanName,有的话会判断是否匹配,匹配则不会加入spring容器
			// 不匹配则抛出异常,没有则直接加入spring容器
			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;
}
  • 扫描bean的代码在findCandidateComponents中,进入
  • addCandidateComponentsFromIndex方法就是读取META-INF目录下的缓存文件
  • 解析原理和scanCandidateComponents一样
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
	/**
	 *	  //解析是否有文件写的有component注解
	 *    if()里面就是判断META-INF目录下面是否有写components文件
	 *   (在该文件里面可以直接定义bean)然后在解析这个文件,其逻辑大致和下面一样
	 */
	if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
		return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
	} else {
		return scanCandidateComponents(basePackage);
	}
}
  • 该方法主要是获得扫描路径下面的所有file对象(.class)
  • 然后读取注解信息,判断与excludeFilters、includeFilters是否匹配以及Conditional条件判断
  • 最后判断是否独立的非接口非抽象类的普通类,或者@Lookup注解的抽象类,最终返回BeanDefinition集合
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
	Set<BeanDefinition> candidates = new LinkedHashSet<>();
	try {
		// 获取basePackage下所有的文件资源
		// classpath*:/**/*.class
		String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
				resolveBasePackage(basePackage) + '/' + this.resourcePattern;
		// classpath文件下的所有file对象
		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);
				// 判断是不是一个bean
				if (isCandidateComponent(metadataReader)) {
					ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
					// 把bean的属性设置进去,主要是名字
					sbd.setSource(resource);
					// 独立的非接口非抽象类的普通类,或者@Lookup注解的抽象类
					if (isCandidateComponent(sbd)) {
						if (debugEnabled) {
							logger.debug("Identified candidate component class: " + resource);
						}
						// 添加到返回的符合扫描的候选bean集合中
						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;
}

isCandidateComponent判断是不是bean

  • 和排除过滤器匹配,如果匹配成功则此.class不是扫描的bean
  • 先和之前注册的扫描过滤@Component匹配,再判断@Conditional的条件是否满足
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;
}

4、注册配置类(Config.class)

  • register(componentClasses);将配置类转为BeanDefinition放入bean容器

在这里插入图片描述
在这里插入图片描述

  • 配置类bean添加到beanDefinitionMap中,与默认后置处理器存放在一起

在这里插入图片描述

三、总结

  • 本篇文章主要讲述刷新上下文前的准备工作
  • 创建bean工厂容器,也就是map对象,以后缓存单例对象
  • 添加常用注册bean和解析注解的后置处理器
  • new扫描包的类,根据包路径扫描Component的bean

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/148522.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!