春季自定义注释

2022-09-05 00:07:40

我见过很少使用自定义注释的示例。例

@SimpleAnnotation
class SampleBean {
  @SimpleAnnotation
  public String getName() {
    return "AAA";
  }

  public void setName(String name) {
  }

  public int getHeight() {
    return 201;
  }
}

@Target( { ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@interface SimpleAnnotation {
}

谁能说出我们为什么使用它?


答案 1

Spring支持许多注释的“元注释”概念。(我不确定它是否适合所有人。

这意味着您可以构建自己的注释,并使用弹簧“核心”注释之一对注释进行注释。

例如:

@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Service
public @interface MyService {

}

然后,您可以使用此注释代替 。(顺便说一句:,,使用相同的技术“继承”自@Service@Service@Repository@Controller@Component)


大量使用它的一个例子是 “inherit” from 。有关示例和一些解释,请查看春季参考章节:3.9.3 使用限定符微调基于注释的自动布线(示例位于本章末尾。@Qualifier@Genre

使用该技术可以完成的一个非常有用的构造是,它使您能够将多个注释组合成一个(在您的用例中)更有意义的完整。因此,与其在某种类型的每个类上编写相同的两个注释,例如:和(org.springframework.beans.factory.annotation.Qualifier)。您可以创建使用这两个批注进行批注的自定义批注,然后在 Bean 中仅使用这一个自定义批注。(@See 避免弹簧注释 代码气味 使用 Spring 3 自定义注释@Service@Qualifiyer("someting"))

如果你想看看这种技术可以使用多强大,你可以看看上下文和依赖注入框架。


评论中的问题:

@interface内部还定义了一些变量,这意味着什么?

注释(由@Interface定义)的工作方式有点像豆类。如果使用批注,则可以/必须定义此字段的属性。稍后可以通过反射 API 读取这些值。

例如,春季注释:@Controller

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
   String value() default "";
}

带有 name 的字段是可以在没有显式命名的情况下使用的字段:( 是相同的value@Controller("myUrl")@Controller(value="myUrl"))


答案 2

您可以创建自己的元注释,收集其他几个Spring注释,以减少代码中的元样板:

@Service
@Scope(value = "prototype")
@Transactional(readOnly = true, rollbackFor = RuntimeException.class)
public @interface ReadOnlyService {}

然后你可以简单地写:

@ReadOnlyService
public class RoleService {

}

Spring 会找到 ,并在语义上将其替换为:@ReadOnlyService

@Service
@Scope(value = "prototype")
@Transactional(readOnly = true, rollbackFor = RuntimeException.class)
public class RoleService {

}

当然,当您有大量的服务使用同一组Spring注释进行注释时,自定义注释是值得的,这些注释可以用一个命名良好的注释替换。

示例取自:避免弹簧注释代码异味:使用 Spring 3 自定义注释


推荐