关于 spring 注解驱动编程

Stereotype Annotations

本文为读书笔记,如需深刻了解,请深刻文末参考html

@Component 以及其派生类是如何被扫描加载的?

spring3.0以前:java

  1. 配置spring <component-scan basePackage: /> xml 中这一配置的处理原理:Extensible XML authoring

好比: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

组合 Annotations

@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 {
}

什么样的注解能够做为 meta-annotation

下面以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 {
}

看源码:

  1. cache pointcut: CacheOperationSourcePointcut -> CacheOperationSource -> AnnotatedElementUtils(支持解析 组合annotation)

  2. cahce advice: AbstractBeanFactoryPointcutAdvisor

  3. proxy bean: CacheProxyFactoryBean 另外再额外问题,CacheProxyFactoryBean何时加载?

因此是否支持组合注解,由该注解的处理类决定。

咱们猜想spring会解析classpath下全部的注解,才能为其建立代理类。

使用 spring @AliasFor

@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.

  1. 默认同名属性覆盖规则:
@Service
@interface MyAnnotation{
 String value() default "";
}

@Componnet
@interface Service{
String value() default "";
}

以上注解都含有value属性,因此默认 MyAnnotation 会覆盖Service中的属性value。

  1. 显示覆盖的需求
@Service
@interface MyAnnotation{
	@AliasFor("value")
   String serviceValue() default "";
}

使用@AliasFor

  1. @AliasFor是否可传递 这部分须要本身写代码测试。

参考

[1] 小马哥,《Spring Boot 编程思想》, 电子工业出版社, 2019.

相关文章
相关标签/搜索