註解能夠減小代碼的開發量,spring提供了豐富的註解功能。咱們可能會被問到,spring的註解究竟是什麼觸發的呢?今天以spring最常使用的一個註解autowired來跟蹤代碼,進行debug。java
做用:Marks a constructor, field, setter method or config method as to be autowired by Spring's dependency injection facilities.spring
定義:api
@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; }
首先,@Target起到什麼做用呢?咱們來看jdk的說明:app
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定義:ide
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { ElementType[] value(); }
註解代表適用於哪一種程序元素,程序元素有如下幾種:post
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})ui
首先,做用: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.CLASSthis
簡單的說就是做用域
而後咱們看其定義:
@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 }
做用: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
它的註冊過程以下:
註冊的註解相關處理器代碼以下:
/** * 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
構造方法的調用鏈
AbstractAutowireCapableBeanFactory#createBean()-->AbstractAutowireCapableBeanFactory#doCreateBean()-->
AbstractAutowireCapableBeanFactory#createBeanInstance()-->
AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors()-->
AutowiredAnnotationBeanPostProcessor#determineConstructorsFromBeanPostProcessors()
基於成員變量的註解自動注入
AbstractAutowireCapableBeanFactory#createBean()-->AbstractAutowireCapableBeanFactory#doCreateBean()-->
AbstractAutowireCapableBeanFactory#populateBean()-->AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues()-->
InjectionMetadata#inject()-->AutowiredFieldElement#inject()/AutowiredMethodElement#inject()
Spring框架從建立伊始就致力於爲複雜問題提供強大的、非侵入性的解決方案。開始時Spring使用XML配置文件數量引入定製命名空間功能。
Spring 2.5推出了一整套註解,做爲基於XML的配置的可選方案。註解可用於Spring管理對象的自動發現、依賴注入、生命週期方法、Web層配置和單元/集成測試。
spring註解確實提升了開發效率,但一直以來,對spring註解的工做原理都處於只知其一;不知其二的狀態,使用註解過程當中碰到問題,也是經過搜索或者屢次嘗試的方式來驗證,爲了更好的工做,趁着有時間把how spring annotation works這件事作起來。