本文爲讀書筆記,如需深刻了解,請深刻文末參考html
spring3.0以前:java
好比:spring
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Repository { /** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any */ String value() default ""; }
basePackage: ->ContextNameSpaceHandler-> ComponentScanBeanBeanDefinitionParser ->MetadataReader(存儲類的信息,包括註解信息) -> ClassPathScanningCandidateComponentProvider ->Typefilter(決定是否加載成Spring Bean)編程
由於 @Component 註解的信息也會被MetadataReader讀取到,因此包含@Conponent的類也會被加載。ide
// 默認filter protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); // ..... }
知道原理以後,spring提供了可擴展,支持增長Typefilter,這樣就不須要依賴spring的 @Component 註解了。測試
Dubbo 2.5.8 @Service的實現也是如此,請參考: ServiceAnnotationBeanPostProcessor.this
@Repository --@MyANNOTATION ----@Component
關鍵class AnnotationAttributesReadingVisitor. 結論:spring2 支持1層,spring3,支持兩層,spring4支持多層。spa
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { }
下面以spring @Cacheable爲例子: @Cacheable.net
<p>This annotation may be used as a <em>meta-annotation</em> to create custom代理
<em>composed annotations</em> with attribute overrides.
@Cacheable是經過AOP的方式工做的,那麼, AOP又是怎麼找到咱們的SlowService的呢:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Cacheable(cacheNames="books", key="#isbn") public @interface SlowService { }
看源碼:
cache pointcut: CacheOperationSourcePointcut
-> CacheOperationSource -> AnnotatedElementUtils(支持解析 組合annotation)
cahce advice: AbstractBeanFactoryPointcutAdvisor
proxy bean: CacheProxyFactoryBean
另外再額外問題,CacheProxyFactoryBean何時加載?
因此是否支持組合註解,由該註解的處理類決定。
咱們猜想spring會解析classpath下全部的註解,才能爲其建立代理類。
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Documented public @interface AliasFor { @AliasFor("attribute") String value() default ""; @AliasFor("value") String attribute() default ""; Class<? extends Annotation> annotation() default Annotation.class; }
在組合註解中會有屬性覆蓋的問題,若是屬性同名的話,覆蓋規則是怎麼樣的?如何顯示覆蓋? 首先,註解解析完以後,註解的屬性會存儲在, AnnotationAttributes
中
LinkedHashMap subclass representing annotation attribute key-value pairs as read by AnnotationUtils, AnnotatedElementUtils, and Spring's reflection- and ASM-based AnnotationMetadata implementations. Provides 'pseudo-reification' to avoid noisy Map generics in the calling code as well as convenience methods for looking up annotation attributes in a type-safe fashion.
@Service @interface MyAnnotation{ String value() default ""; } @Componnet @interface Service{ String value() default ""; }
以上註解都含有value屬性,因此默認 MyAnnotation 會覆蓋Service中的屬性value。
@Service @interface MyAnnotation{ @AliasFor("value") String serviceValue() default ""; }
使用@AliasFor
[1] 小馬哥,《Spring Boot 編程思想》, 電子工業出版社, 2019.