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来配置属性。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值