08spring源码分析-注解驱动如何实现

Spring注解源码分析

我们知道如果想使用spring注解你需要在applicationContext.xml配置文件中设置context:component-scan base-package='xxx'这样spring会帮助我们扫描你所设置的目录里面所有的Bean,如果Bean上面有相应的@Service,@Controller注解(当然还有其他的,这里就不一一列出来),那么Spring的IOC容器将会帮我实例对象,设置属性。

分析spring如果实现注解驱动

还是从spring配置文件的命名空间入手,不清楚的可以参考我之前的文章。找到spring-context包进入文件里面找到src/main/resources/META-INF/spring.handlers这样你可以看到一下内容:

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

可以看到context命名空间解析的类org.springframework.context.config.ContextNamespaceHandler所以可以直接定位到spring扫描的过程。

spring源码分析-ContextNamespaceHandler

//组件扫描
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());

整个扫描包路径的过程如下:

  • 取出自定义base-package路径

  • 创建ClassPathBeanDefinitionScanner对象并且设置springIOC容器所关心的注解@Component换言之:只要类定义上面有@Component注解那么我们的扫描器就需要处理这个类。

    • 设置BeanName生成工具(这里是生成类名的工具有默认的beanName,也有自定义@Service("abc"))
  • 开始扫描包,使用ClassReader扫描所有类可以得到类的信息,对比是否有@Component注解,如果有生成BeanDefinition=ScannedGenericBeanDefinition

  • 注册Spring内置的BeanPostProcessor对象。默认有8个org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)主要需要注意的有四个

    • ConfigurationClassPostProcessor:处理配置类
    • AutowiredAnnotationBeanPostProcessor:处理@Autowired帮助类注入属性
    • RequiredAnnotationBeanPostProcessor:处理@required
    • CommonAnnotationBeanPostProcessor:处理@Resource帮助类注入属性
    • 入口代码:
        if (annotationConfig) {
      //这里会注册很多内容BeanPostProcessor类
            Set<BeanDefinitionHolder> processorDefinitions =AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
            for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
                compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
            }
        }

上面只是注册了所有内置Annotation工具类,还没有实例化。接下来我们要进入refresh()方法看看基于注解的类实例化过程

注解类实例过程

在前面基于注解的类已经被扫描成为ScannedGenericBeanDefinition现在就要实例化了。再refresh()方法中首先需要注册前面说的内置处理Annotation类的工具类,没错就是这几个:

2 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
3 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
4 = "org.springframework.context.annotation.internalRequiredAnnotationProcessor"
5 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
6 = "org.springframework.context.event.internalEventListenerProcessor"
7 = "org.springframework.context.event.internalEventListenerFactory"
//最终这些类变为:
0 = {ApplicationContextAwareProcessor@1792} 
1 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@1961} 
2 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@2193} 
3 = {CommonAnnotationBeanPostProcessor@2135} 
4 = {AutowiredAnnotationBeanPostProcessor@1991} 
5 = {RequiredAnnotationBeanPostProcessor@2107} 
6 = {ApplicationListenerDetector@2194} 

入口在:registerBeanPostProcessors(beanFactory);这里会将上面的类注册到IOC容器中,然后根据Bean的生命周期中的第6步设置属性,依据Annotation的方式注入属性:CommonAnnotationBeanPostProcessor来处理属性的注入。我们使用了@Resource来配置属性。

整个实例的全流程可以参考另一篇文章

07spring源码分析-从Bean的生命周期分析IOC创建对象过程

//TODO 学习ClassReader对象
classReader
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容

  • | 题记昨天是我的老单位深圳电台开播三十周年的纪念庆典,早已不是圈内人的我自然未能躬逢盛会,但旧同僚朋友圈的不断刷...
    柳七归来阅读 545评论 0 0
  • 昨夜忽起感慨,写了一段流心的文字,“人啊,从来都只是会被自己在乎的东西伤害。”、“这爱恨煎熬,得失过后,不经意便是...
    化浊阅读 272评论 0 2
  • 年华易逝,不知不觉间,步入了老年。 人活这一辈子,年轻的时候追求成功和荣誉,来证明自己的价值。年老了,就跟随自己的...
    雨天_7afd阅读 284评论 0 11