zoukankan      html  css  js  c++  java
  • @AliasFor 注解

    Spring 框架提供了很丰富的注解可以让我们很方便的进行 Spring 配置,今天要讲的注解——@AliasFor之前你可能并没有关注过,因为平时开发时我们的确不太会用到。

    我关注到这个注解是因为我经常翻看 Spring 的源代码,在 Spring 提供的注解中大量的用到了这个注解,对这个注解不熟悉的话会影响你对代码的判断,而且有些代码看的总是似懂非懂的,很难受(强迫症,哈哈),比如说下面这段代码。

    @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 {
        
    	@AliasFor(annotation = EnableAutoConfiguration.class)
    	Class<?>[] exclude() default {};
    
    	@AliasFor(annotation = EnableAutoConfiguration.class)
    	String[] excludeName() default {};
        
    	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    	String[] scanBasePackages() default {};
    
    	@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
    	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
    
    	@AliasFor(annotation = Configuration.class)
    	boolean proxyBeanMethods() default true;
    
    }
    

    上面的代码大致能“猜测”出 @AliasFor 是为了属性起别名,但是 @AliasFor 的使用场景,使用方式,实现原理是什么?这博客就简单介绍下。

    @AliasFor 注解的几种使用方式

    1. 在同一个注解中显示使用,将注解中的多个属性互相设置别名

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Mapping
    public @interface RequestMapping {
        
    	@AliasFor("path")
    	String[] value() default {};
    
    	@AliasFor("value")
    	String[] path() default {};
        
        //...
    }
    

    为什么要给 value 属性和 path 属相互相设置别名也是有原因的。我们知道在 Spring 中给 value 属性设置值是可以省略属性的,比如可以写成:

    RequestMapping("/foo")
    

    这样写比较简洁,但是这样可读性不高,我们并不知道 value 属性代表什么意思。如果给这个属相设置一个 path 别名的话我们就知道这个是在设置路径。

    但是要注意一点,@AliasFor 标签有一些使用限制:

    • 互为别名的属性属性值类型,默认值,都是相同的;
    • 互为别名的注解必须成对出现,比如 value 属性添加了@AliasFor(“path”),那么 path 属性就必须添加@AliasFor(“value”);
    • 另外还有一点,互为别名的属性必须定义默认值。

    那么如果违反了别名的定义,在使用过程中就会报错。

    2. 给元注解中的属性设定别名

    @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 {
    
    	@AliasFor(annotation = EnableAutoConfiguration.class)
    	Class<?>[] exclude() default {};
    
    	@AliasFor(annotation = EnableAutoConfiguration.class)
    	String[] excludeName() default {};
        
    	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    	String[] scanBasePackages() default {};
        //...
    }
    

    我们来看 @SpringBootApplication 这个注解,这个注解是有其他几个注解“组合”而成的。下面的代码就是在给@ComponentScan 注解的basePackages属性设置别名scanBasePackages。如果不设置attribute属性的话就是在给元注解的同名属性设置别名。

    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};
    

    这种使用方式的好处是可以将几个注解的功能组合成一个新的注解。

    @AliasFor 的实现代码

    贴大片代码的事就不干了。@AliasFor 的具体实现在AnnotationUtils.findAnnotation 中,代码大家自己翻看吧。


    参考

    人生的主旋律其实是苦难,快乐才是稀缺资源。在困难中寻找快乐,才显得珍贵~
  • 相关阅读:
    Nodejs怎样在服务端写定时脚本,自动备份MongoDB数据库,并记录日志
    nodejs-websocket初使用
    CSS3的复习笔记
    ES6的新增特性
    Windows下初体验MongoDB数据库
    Node.js数据库的配置,封装query
    Nuxt+Vuex初体验
    Vue+Vuex初体验
    github二级域名配置
    钉钉静默安装
  • 原文地址:https://www.cnblogs.com/54chensongxia/p/14385621.html
Copyright © 2011-2022 走看看