1. 背景

注解可以减少代码的开发量,spring提供了丰富的注解功能。我们可能会被问到,spring的注解到底是什么触发的呢?今天以spring最常使用的一个注解autowired来跟踪代码,进行debug。

2. Autowired的定义及作用

作用:Marks a constructor, field, setter method or config method as to be autowired by Spring's dependency injection facilities.

定义:

@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired { /**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true; }

2.1 @Target

首先,@Target起到什么作用呢?我们来看jdk的说明:

Indicates the kinds of program element to which an annotation type is applicable. If a Target meta-annotation is not present on an annotation type declaration, the declared type may be used on any program element. If such a meta-annotation is present, the compiler will enforce the specified usage restriction.

其次,@Target定义:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}

注解表明适用于哪种程序元素,程序元素有以下几种:

public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE, /** Field declaration (includes enum constants) */
FIELD, /** Method declaration */
METHOD, /** Parameter declaration */
PARAMETER, /** Constructor declaration */
CONSTRUCTOR, /** Local variable declaration */
LOCAL_VARIABLE, /** Annotation type declaration */
ANNOTATION_TYPE, /** Package declaration */
PACKAGE
}

最后,Target使用方式:

@Target(value={ANNOTATION_TYPE})

2.2 @Retention

首先,作用:Indicates how long annotations with the annotated type are to be retained. If no Retention annotation is present on an annotation type declaration, the retention policy defaults to RetentionPolicy.CLASS

简单的说就是作用域

然后我们看其定义:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}

最后,使用方式:

@Retention(value=RetentionPolicy )

RetentionPolicy 作用域定义

public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE, /**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS, /**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}

2.3.@Documented

作用:Indicates that annotations with a type are to be documented by javadoc and similar tools by default. This type should be used to annotate the declarations of types whose annotations affect the use of annotated elements by their clients. If a type declaration is annotated with Documented, its annotations become part of the public API of the annotated elements.简单的说,可以成为api的一部分。

定义:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

使用:@Documented

3.注解实现类AutowiredAnnotationBeanPostProcessor的注册

它的注册过程如下:

注册的注解相关处理器代码如下:

/**
* Register all relevant annotation post processors in the given registry.
* @param registry the registry to operate on
* @param source the configuration source element (already extracted)
* that this registration was triggered from. May be {@code null}.
* @return a Set of BeanDefinitionHolders, containing all bean definitions
* that have actually been registered by this call
*/
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) { 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<BeanDefinitionHolder>(4); 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));
} 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));
} if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
} // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
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));
} return beanDefs;
}

通过代码,我们可以看到注册的注解处理器有:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor对应于ConfigurationClassPostProcessor

org.springframework.context.annotation.internalAutowiredAnnotationProcessor对应于AutowiredAnnotationBeanPostProcessor

org.springframework.context.annotation.internalRequiredAnnotationProcessor对应于RequiredAnnotationBeanPostProcessor

org.springframework.context.annotation.internalCommonAnnotationProcessor对应于CommonAnnotationBeanPostProcessor

org.springframework.context.annotation.internalPersistenceAnnotationProcessor对应于PersistenceAnnotationBeanPostProcessor

4.注解实现类AutowiredAnnotationBeanPostProcessor使用

构造方法的调用链

AbstractAutowireCapableBeanFactory#createBean()-->AbstractAutowireCapableBeanFactory#doCreateBean()-->

AbstractAutowireCapableBeanFactory#createBeanInstance()-->

AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors()-->

AutowiredAnnotationBeanPostProcessor#determineConstructorsFromBeanPostProcessors()

基于成员变量的注解自动注入

AbstractAutowireCapableBeanFactory#createBean()-->AbstractAutowireCapableBeanFactory#doCreateBean()-->

AbstractAutowireCapableBeanFactory#populateBean()-->AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues()-->

InjectionMetadata#inject()-->AutowiredFieldElement#inject()/AutowiredMethodElement#inject()

5.小结

Spring框架从创建伊始就致力于为复杂问题提供强大的、非侵入性的解决方案。开始时Spring使用XML配置文件数量引入定制命名空间功能。

Spring 2.5推出了一整套注解,作为基于XML的配置的可选方案。注解可用于Spring管理对象的自动发现、依赖注入、生命周期方法、Web层配置和单元/集成测试。

   spring注解确实提高了开发效率,但一直以来,对spring注解的工作原理都处于一知半解的状态,使用注解过程中碰到问题,也是通过搜索或者多次尝试的方式来验证,为了更好的工作,趁着有时间把how spring annotation works这件事做起来。

spring注解源码分析--how does autowired works?的更多相关文章

  1. Spring Ioc源码分析系列--@Autowired注解的实现原理

    Spring Ioc源码分析系列--@Autowired注解的实现原理 前言 前面系列文章分析了一把Spring Ioc的源码,是不是云里雾里,感觉并没有跟实际开发搭上半毛钱关系?看了一遍下来,对我的 ...

  2. Spring笔记(5) - 声明式事务@EnableTransactionManagement注解源码分析

    一.背景 前面详解了实现Spring事务的两种方式的不同实现:编程式事务和声明式事务,对于配置都使用到了xml配置,今天介绍Spring事务的注解开发,例如下面例子: 配置类:注册数据源.JDBC模板 ...

  3. Spring IoC 源码分析 (基于注解) 之 包扫描

    在上篇文章Spring IoC 源码分析 (基于注解) 一我们分析到,我们通过AnnotationConfigApplicationContext类传入一个包路径启动Spring之后,会首先初始化包扫 ...

  4. 精尽Spring Boot源码分析 - 剖析 @SpringBootApplication 注解

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  5. 精尽Spring Boot源码分析 - @ConfigurationProperties 注解的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  6. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

  7. Spring Security 源码分析 --- WebSecurity

    概述 spring security 源码分析系列文章. 源码分析 我们想一下,我们使用 ss 框架的步骤是怎么样的. @Configuration @EnableWebSecurity @Enabl ...

  8. [心得体会]spring事务源码分析

    spring事务源码分析 1. 事务的初始化注册(从 @EnableTransactionManagement 开始) @Import(TransactionManagementConfigurati ...

  9. Spring Ioc源码分析系列--Bean实例化过程(二)

    Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...

随机推荐

  1. C++ std::set

    std::set template < class T, // set::key_type/value_type class Compare = less<T>, // set::k ...

  2. 【资源】.Net 入门@提高 - 逆天的高薪之路!

     入门看视频,提高看书籍,飘升做项目.老练研开源,高手读外文,大牛讲低调~    官方学习计划 http://www.cnblogs.com/dunitian/p/5667901.html ----- ...

  3. Hive安装配置指北(含Hive Metastore详解)

    个人主页: http://www.linbingdong.com 本文介绍Hive安装配置的整个过程,包括MySQL.Hive及Metastore的安装配置,并分析了Metastore三种配置方式的区 ...

  4. SDWebImage源码解读 之 NSData+ImageContentType

    第一篇 前言 从今天开始,我将开启一段源码解读的旅途了.在这里先暂时不透露具体解读的源码到底是哪些?因为也可能随着解读的进行会更改计划.但能够肯定的是,这一系列之中肯定会有Swift版本的代码. 说说 ...

  5. 利用for循环找出1000以内的质数

    var n=0; for(var i=2;i<=1000;i++){  var zhishu=true;  for(var j=2;j<i;j++){    if(i%j==0){    ...

  6. win10电脑优化

    Windows10必做的优化 --道心 关闭服务 右键点击"此电脑",选择"管理",进入"计算机管理"窗口. 在左侧的菜单选择"服 ...

  7. python-time 模块

    1.时间戳是以秒为单位的浮点小数,时间戳以自1970年1月1日午夜到现在经过了的时间来表示 2.时间模块引入方式:import time 3.返回时间戳 time.time() 4.返回时间元组:ti ...

  8. mono for android学习过程系列教程(2)

    接着上一讲继续开始写,今天介绍的是安卓的基本组成结构. 在大多数情况下,MONO FOR ANDROID的命名空间和Android的命名空间 是互相映射的.有时候需要大小写,非字母数字字符的用法以及名 ...

  9. CSharpGL(31)[译]OpenGL渲染管道那些事

    CSharpGL(31)[译]OpenGL渲染管道那些事 +BIT祝威+悄悄在此留下版了个权的信息说: 开始 自认为对OpenGL的掌握到了一个小瓶颈,现在回头细细地捋一遍OpenGL渲染管道应当是一 ...

  10. The type javax.ws.rs.core.MediaType cannot be resolved. It is indirectly referenced from required .class files

    看到了http://stackoverflow.com/questions/5547162/eclipse-error-indirectly-referenced-from-required-clas ...