A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 小江哥 黑马粉丝团   /  2019-11-6 19:34  /  1377 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

在Spring的众多注解中,经常会发现很多注解的不同属性起着相同的作用,比如@RequestMapping的value属性和path属性,这就需要做一些基本的限制,比如value和path的值不能冲突,比如任意设置value或者设置path属性的值,都能够通过另一个属性来获取值等等。为了统一处理这些情况,Spring创建了@AliasFor标签。

使用
@AliasFor标签有几种使用方式。

1,在同一个注解内显示使用;比如在@RequestMapping中的使用示例:
[Java] 纯文本查看 复制代码
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
 
    @AliasFor("path")
    String[] value() default {};
 
    @AliasFor("value")
    String[] path() default {};
 
    //...
}

又比如@ContextConfiguration注解中的value和locations属性:
[Java] 纯文本查看 复制代码
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ContextConfiguration {
    @AliasFor("locations")
    String[] value() default {};
 
    @AliasFor("value")
    String[] locations() default {};
    //...
}

在同一个注解中成对使用即可,比如示例代码中,value和path就是互为别名。但是要注意一点,@AliasFor标签有一些使用限制,但是这应该能想到的,比如要求互为别名的属性属性值类型,默认值,都是相同的,互为别名的注解必须成对出现,比如value属性添加了@AliasFor(“path”),那么path属性就必须添加@AliasFor(“value”),另外还有一点,互为别名的属性必须定义默认值。

那么如果违反了别名的定义,在使用过程中就会报错,我们来做个简单测试:
[Java] 纯文本查看 复制代码
@ContextConfiguration(value = "aa.xml", locations = "bb.xml")
public class AnnotationUtilsTest {
    @Test
    public void testAliasfor() {
        ContextConfiguration cc = AnnotationUtils.findAnnotation(getClass(),
                ContextConfiguration.class);
        System.out.println(
                StringUtils.arrayToCommaDelimitedString(cc.locations()));
        System.out.println(StringUtils.arrayToCommaDelimitedString(cc.value()));
    }
}

执行测试,报错;value和locations互为别名,不能同时设置;

稍微调整一下代码:

[Java] 纯文本查看 复制代码
@MyAnnotation
@ContextConfiguration(value = "aa.xml", locations = "aa.xml")
public class AnnotationUtilsTest {

运行测试,均打印出:

[Java] 纯文本查看 复制代码
aa.xml
aa.xml

2,显示的覆盖元注解中的属性;
先来看一段代码:

[Java] 纯文本查看 复制代码
@RunWith(SpringJUnit4ClassRunner.class)[/font][/color][/p]@ContextConfiguration(classes = AopConfig.class)
public class AopUtilsTest {
这段代码是一个非常熟悉的基于JavaConfig的Spring测试代码;假如现在我有个癖好,我觉得每次写@ContextConfiguration(classes = AopConfig.class)太麻烦了,我想写得简单一点,我就可以定义一个这样的标签:

[Java] 纯文本查看 复制代码
@Retention(RetentionPolicy.RUNTIME)
@ContextConfiguration
public @interface STC {
 
    @AliasFor(value = "classes", annotation = ContextConfiguration.class)
    Class<?>[] cs() default {};
 
}

1,因为@ContextConfiguration注解本身被定义为@Inherited的,所以我们的STC注解即可理解为继承了@ContextConfiguration注解;
2,我觉得classes属性太长了,所以我创建了一个cs属性,为了让这个属性等同于@ContextConfiguration属性中的classes属性,我使用了@AliasFor标签,分别设置了value(即作为哪个属性的别名)和annotation(即作为哪个注解);

使用我们的STC:
[Java] 纯文本查看 复制代码
@RunWith(SpringJUnit4ClassRunner.class)
@STC(cs = AopConfig.class)
public class AopUtilsTest {
 
    @Autowired
    private IEmployeeService service;


正常运行;
这就是@AliasFor标签的第二种用法,显示的为元注解中的属性起别名;这时候也有一些限制,比如属性类型,属性默认值必须相同;当然,在这种使用情况下,@AliasFor只能为作为当前注解的元注解起别名;

3,在一个注解中隐式声明别名;
这种使用方式和第二种使用方式比较相似,我们直接使用Spring官方文档的例子:
[Java] 纯文本查看 复制代码
 @ContextConfiguration
 public @interface MyTestConfig {
 
    @AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
    String[] value() default {};
 
    @AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
    String[] groovyScripts() default {};
 
    @AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
    String[] xmlFiles() default {};
 }


可以看到,在MyTestConfig注解中,为value,groovyScripts,xmlFiles都定义了别名@AliasFor(annotation = ContextConfiguration.class, attribute = “locations”),所以,其实在这个注解中,value、groovyScripts和xmlFiles也互为别名,这个就是所谓的在统一注解中的隐式别名方式;

4,别名的传递;
@AliasFor注解是允许别名之间的传递的,简单理解,如果A是B的别名,并且B是C的别名,那么A是C的别名;
我们看一个例子:
[Java] 纯文本查看 复制代码
 @MyTestConfig
 public @interface GroovyOrXmlTestConfig {
 
    @AliasFor(annotation = MyTestConfig.class, attribute = "groovyScripts")
    String[] groovy() default {};
 
    @AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
    String[] xml() default {};
 }




转载:https://blog.csdn.net/wolfcode_cn/article/details/80654730

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马