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源码加载bean定义信息 loadBeanDefinitions-自定义标签解析(component-scan-2) -> 正文阅读

[Java知识库]spring源码加载bean定义信息 loadBeanDefinitions-自定义标签解析(component-scan-2)

上篇传送门
上篇大体了解了下执行BFPP的过程,BFPP的作用也介绍了,但是并没有深入看下如何实现的,接下来咱们了解下context:component-scan 标签是如何解析的

概述

咱们开发过程中会使用到很多的注解配置等,这些注解必须要被扫描到才能被识别

spring中标签分为几种

分为两种

  1. 标签
  2. 自定义标签(除了bean标签外)

源码之前先了解两个类

  1. DefaultBeanDefinitionDocumentReader 调度者
  2. BeanDefinitionParserDelegate 解析策略类用于策略模式的指令执行者
  3. NamespaceHandler 策略抽象,用于制定规范

源码

咱们继续回到DefaultBeanDefinitionDocumentReader.parseBeanDefinitions方法

for (int i = 0; i < nl.getLength(); i++) {
	Node node = nl.item(i);
	if (node instanceof Element) {
		Element ele = (Element) node;
		if (delegate.isDefaultNamespace(ele)) {
			//只有解析bean标签的时候才是默认标签,其他事自定义标签
			//解析bean标签
			parseDefaultElement(ele, delegate);
		}else {
			//使用策略类解析自定义标签
			delegate.parseCustomElement(ele);
		}
	}
}

BeanDefinitionParserDelegate.parseCustomElement 解析自定义标签,使用策略模式

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
	//根据节点名称获取对应命名空间
	String namespaceUri = getNamespaceURI(ele);
	if (namespaceUri == null) {
		return null;
	}
	//获取处理器
	//具体在spring-context/resources/spring.handlers文件中配置
	NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
	if (handler == null) {
		return null;
	}
	//使用处理器进行解析
	return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
DefaultNamespaceHandlerResolver.resolve 得到对应的命令空间的处理器
public NamespaceHandler resolve(String namespaceUri) {
	//获取spring-context/META-INF/spring.handlers文件中的缓存
	Map<String, Object> handlerMappings = getHandlerMappings();
	Object handlerOrClassName = handlerMappings.get(namespaceUri);
	if (handlerOrClassName == null) {
		return null;
	}else if (handlerOrClassName instanceof NamespaceHandler) {
		//如果实例化过了
		return (NamespaceHandler) handlerOrClassName;
	}else {
		String className = (String) handlerOrClassName;
		try {
			Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
			if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
				throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
			}
			//实例化
			NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
			//初始化
			namespaceHandler.init();
			//替换缓存中的value为对象
			handlerMappings.put(namespaceUri, namespaceHandler);
			return namespaceHandler;
		}catch (ClassNotFoundException ex) {
			throw new FatalBeanException("Could not find NamespaceHandler class [" + className +"] for namespace [" + namespaceUri + "]", ex);
		}
		catch (LinkageError err) {
			throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" +className + "] for namespace [" + namespaceUri + "]", err);
		}
	}
}
NamespaceHandlerSupport.parse 使用处理器解析元素标签(使用策略模式)
public BeanDefinition parse(Element element, ParserContext parserContext) {
	//获取到标签的解析器 从ContextNamespaceHandler里面获取
	BeanDefinitionParser parser = findParserForElement(element, parserContext);
	return (parser != null ? parser.parse(element, parserContext) : null);
}
NamespaceHandlerSupport.parse 使用处理器解析元素标签

在这里插入图片描述

private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
	//元素标签的名称
	String localName = parserContext.getDelegate().getLocalName(element);
	//从ContextNamespaceHandler里面定义的多个标签中获取出对应的解析类
	//这里获取到的是ComponentScanBeanDefinitionParser
	BeanDefinitionParser parser = this.parsers.get(localName);
	if (parser == null) {
		parserContext.getReaderContext().fatal(
				"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
	}
	return parser;
}

ComponentScanBeanDefinitionParser.parse 真正开始解析了

public BeanDefinition parse(Element element, ParserContext parserContext) {
	//获取包扫描路径
	String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
	//使用PropertyPlaceholderHelper处理包路径
	//处理${}占位符
	basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
	//使用分隔符分割,就是咱们可以在package中写多个路径 如:“com.msg.package2,;com.msg.package2”
	String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
	// 配置扫描器
	ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
	// 开始扫描,并创建出BeanDefinitionHolder
	Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
	//开始注册组件
	registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
	return null;
}
ComponentScanBeanDefinitionParser.configureScanner 配置扫描器
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
	boolean useDefaultFilters = true;
	if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
		useDefaultFilters = Boolean.parseBoolean(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
	}

	// 创建一个ClassPathBeanDefinitionScanner类路径扫描器并设置相应的属性
	ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
	//设置BeanDefinitionDefaults对象
	scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
	scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
	if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
		scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
	}
	try {
		// 如果指定了 name-generator 属性,设置对应bean名称的生成器 如:<bean class=“xxx.xxx.xxx”> 这个类创建完成后对应的名字是什么(就是id值)
		parseBeanNameGenerator(element, scanner);
	}catch (Exception ex) {
		parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
	}
	try {
		// 设置 Scope 解析相关信息
		<context:component-scan base-package="com">
			<context:exclude-filter type="annotation" expression="com.msg"/>
			<context:include-filter type="annotation" expression="com.msg"/>
		</context:component-scan>
		parseScope(element, scanner);
	}catch (Exception ex) {
		parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
	}
	// 设置子标签过滤、包含相关信息
	parseTypeFilters(element, scanner, parserContext);
	return scanner;
}
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) {
		// 找到符合条件的Component组件(类上标注了@Component注解)
		//classpath*:com/msgqu/debug/**/*.class
		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
		for (BeanDefinition candidate : candidates) {
			// 解析作用域及是否需要代理作用域
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			candidate.setScope(scopeMetadata.getScopeName());
			//生成bean的名称(AnnotationBeanNameGenerator)
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
			if (candidate instanceof AbstractBeanDefinition) {
				//设置基本属性,lazy、AutowireMode...
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			if (candidate instanceof AnnotatedBeanDefinition) {
				//设置注解信息 Lazy、Primary、DependsOn、Role、Description
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}
			// 检查是否符合条件 如:是不是已经注册过了
			if (checkCandidate(beanName, candidate)) {
				// 创建bean定义信息的包装类
				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				// 如果需要代理,重新生成definitionHolder
				definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
				//记录扫描后的容器中返回
				beanDefinitions.add(definitionHolder);
				//注册bean定义信息到工厂中
				registerBeanDefinition(definitionHolder, this.registry);
			}
		}
	}
	return beanDefinitions;
}
ComponentScanBeanDefinitionParser.registerComponents 注册必要的组件
protected void registerComponents(XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {

		Object source = readerContext.extractSource(element);
		CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
		//创建内部bean以及引用
		for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
			compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
		}

		// Register annotation config processors, if necessary.
		boolean annotationConfig = true;
		if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
			annotationConfig = Boolean.parseBoolean(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
		}
		if (annotationConfig) {
			//注册内部使用的定义信息
			Set<BeanDefinitionHolder> processorDefinitions = AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
			for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
				compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
			}
		}
		//扩展方法
		readerContext.fireComponentRegistered(compositeDef);
	}
AnnotationConfigUtils.registerAnnotationConfigProcessors 注册内部使用的对象

方法执行前
在这里插入图片描述
方法执行后
在这里插入图片描述

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {
	//对bean工厂做配置
	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);
	//ConfigurationClassPostProcessor是一个BeanFactory的后置处理器,因此它的主要功能是参与BeanFactory的建造,在这个类中,会解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Import等注解
	//借博主的描述,后面咱们还会详细在invokBFPP方法中讲解
	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));
	}
	//支持 @Autowired 和 @Value 注解的支持也支持 @Inject 注解,也可以给setter 方法进行注入。也包括对 @Lookup 注解解析
	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));
	}
	//对@PostConstruct和@PreDestroy注解的处理,完成bean初始化前和销毁前的回调
	//对@Resource注解的处理,完成依赖字段的注入
	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;
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-16 22:07:36  更:2022-03-16 22:10:28 
 
开发: 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/24 9:12:19-

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