网站首页 > 技术教程 正文
Annotation的解析机制
我们在使用spring中,经常会在xml中加上<context:component-scan/>标签,然后在需要配置在spring中的类上加上@Component/@Service/@Repository等注解,我们先简单的看看@Service或者@Repository注解,会发现这两个注解都被@Component注解所标识:
想要了解这些注解是如何工作的,就需要先知道component-scan标签做了什么。前文中描述了spring的xml解析机制以及其扩展方式,既然component-scan标签声明在context这个命名空间中,我们可以从ContextNamespaceHandler类入手,此类中有如下代码:
可以看到,component-scan标签使用了ComponentScanBeanDefinitionParser类做bean的解析,此类中的核心代码比较容易理解,先扫描类路径,识别出@Component注解标识的类或以@Component作为元注解的注解标识的类,将扫描到的bean注册到BeanDefinitionRegistry中:
从ClassPathBeanDefinitionScanner的doScan方法中进入,很容易发现component-scan的类路径扫描策略,它并没有逐个加载class,而是通过读取class文件得到类的元数据的方式做的类识别,关键代码段如下:
registerComponents方法的逻辑前半部分是在处理scanner扫描出来的bean,而后半部分则略有不同,后半部分向spring中注册注解配置处理相关的PostProcessor,主要逻辑是用于处理@Configuration/@ComponentScan注解标识的类以及@Autowired等注解的注入:
进入到AnnotationConfigUtils.registerAnnotationConfigProcessors方法的调用中,可以看到spring注册了多个与注解处理相关的类,其中包括用于处理@Configuration或@ComponentScan注解配置的类ConfigurationClassPostProcessor,注解注入处理类AutowiredAnnotationBeanPostProcessor等,详情可见具体代码:
注册的这些为都是前文描述过的PostProcessor的实现,其中注解注入相关的类是AutowiredAnnotationBeanPostProcessor,前文已经提到过,这里再重点描述一下ConfigurationClassPostProcessor类,此类的定义如下:
ConfigurationClassPostProcessor类是BeanFactoryPostProcessor的实现类(BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口),从ConfigurationClassPostProcessor的postProcessorBeanFactory方法或者postProcessorBeanDefinitionRegistry方法中可以看到注解配置处理的逻辑:
从代码片断中可以看到processConfigBeanDefinitions方法是处理注解的核心方法,进入到此方法中会发现使用了ConfigurationClassParser类做注解解析。 ConfigurationClassParser类的parse方法调用了processConfigurationClass方法,此方法用于处理标识了@Configuration或@ComponentScan的bean,方法中有一段判断是否需要跳过某个class的逻辑:
这里涉及到另一个注解@Conditional,被此注解标识的配置类,在不满足此注解指定的条件时在处理注解配置时会被跳过。
@Import
在使用springboot时,经常会用到@EnableXxx这样的注解,比如开户aop可以使用@EnableAspectJAutoProxy,这里也是使用到了spring为注解配置留的扩展,打开此类可以看到@Import注解的使用:
回到ConfigurationClassParser类中,可以找到处理@Import注解的代码:
首先是collectImports方法,它里面有一个递归调用,用于处理@Import作为元注解的情况,由于有这段逻辑的处理,@EnableAspectJAutoProxy上的元注解@Import才会被识别; 通过processImports方法可以看到@Import的具体处理逻辑,它通过@Import注解中的value属性指定的class获取BeanDefinition对象,逻辑相对较容易理解,这里不做过多解释:
Spring注解的扩展
这里给一个Spring注解扩展的简单示例,在初始化前通过日志打印出spring中配置了哪些bean,通过@Import实现:
在使用时可将@LogBean标识在配置类或者springboot的启动类上:
猜你喜欢
- 2024-10-19 Java 项目编译提示 javax.xml.bind.annotation does not exist 错误
- 2024-10-19 Android annotation包下常用的注解
- 2024-10-19 SpringMVC疑难一:mvc:annotation-dr
- 2024-10-19 Spring 中 AnnotationConfigUtils
- 2024-10-19 spring mvc 配置失效了?(springmvc的配置)
- 2024-10-19 为什么都爱着江南?黛瓦白墙,烟雨朦胧,是文人魂牵梦绕的故乡
- 2024-10-19 Spring框架系列之构造方法底层剖析01
- 2024-10-19 基于.NET6包含DDD,ES,CQRS等概念的开源
- 2024-10-19 spring 中 AnnotationUtils 的常用方法
- 2024-10-19 SpringBoot实战4-Spring基础-IoC容器
欢迎 你 发表评论:
- 10-23Excel计算工龄和年份之差_excel算工龄的公式year
- 10-23Excel YEARFRAC函数:时间的"年份比例尺"详解
- 10-23最常用的10个Excel函数,中文解读,动图演示,易学易用
- 10-23EXCEL中如何计算截止到今日(两个时间中)的时间
- 10-2390%人不知道的Excel神技:DATEDIF 精准计算年龄,告别手动算错!
- 10-23计算工龄及工龄工资(90%的人搞错了):DATE、DATEDIF组合应用
- 10-23Excel中如何计算工作日天数?用这两个函数轻松计算,附新年日历
- 10-23怎样快速提取单元格中的出生日期?用「Ctrl+E」批量搞定
- 最近发表
-
- Excel计算工龄和年份之差_excel算工龄的公式year
- Excel YEARFRAC函数:时间的"年份比例尺"详解
- 最常用的10个Excel函数,中文解读,动图演示,易学易用
- EXCEL中如何计算截止到今日(两个时间中)的时间
- 90%人不知道的Excel神技:DATEDIF 精准计算年龄,告别手动算错!
- 计算工龄及工龄工资(90%的人搞错了):DATE、DATEDIF组合应用
- Excel中如何计算工作日天数?用这两个函数轻松计算,附新年日历
- 怎样快速提取单元格中的出生日期?用「Ctrl+E」批量搞定
- Excel日期函数之DATEDIF函数_excel函数datedif在哪里
- Excel函数-DATEDIF求司龄_exceldatedif函数计算年龄
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)

本文暂时没有评论,来添加一个吧(●'◡'●)