SpringBoot之神秘的注解


声明:本文转载自https://my.oschina.net/qixiaobo025/blog/1580315,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

插播一条广告→2021 ByteDance字节跳动内推←各城市、各方向的岗位都有,大量招人!


背景

  1. 大量的XML让开发者厌恶,因此Spring提供了许多注解来完成各种功能。
  2. 大量的注解让开发者厌恶 ,因此Spring提供了组合注解来完成各种功能。

举例

  1. 最典型的SpringMVC中我们使用如下注解 @Controller
    事实上我们接触到Controller时都会如下说明Controller Service Repository事实上和Component 没有差别 但是Spring后期可能可能条件不同的语义 因此注意使用

    /**  * Indicates that an annotated class is a "Controller" (e.g. a web controller).  *  * <p>This annotation serves as a specialization of {@link Component @Component},  * allowing for implementation classes to be autodetected through classpath scanning.  * It is typically used in combination with annotated handler methods based on the  * {@link org.springframework.web.bind.annotation.RequestMapping} annotation.  *  * @author Arjen Poutsma  * @author Juergen Hoeller  * @since 2.5  * @see Component  * @see org.springframework.web.bind.annotation.RequestMapping  * @see org.springframework.context.annotation.ClassPathBeanDefinitionScanner  */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller {      /**     * 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 "";   }

     

  2. 我们把修饰其他注解的注解称之为Meta Annotation【元注解】
    meta-annotation is an annotation that is declared on another annotation. An annotation is therefore meta-annotated if it is annotated with another annotation. For example, any annotation that is declared to be documented is meta-annotated with @Documented from thejava.lang.annotation package.

  3. 当我们业务越发复杂的情况下我们会大量的使用注解进行组合 比如

    @RestController @RequestMapping("user") public class TbUserController extends AbstractRestController<TbUserVo, TbUserSo, BigInteger> {     @Resource     private TbUserService tbUserService;     }

    这个注解还比较少,但是对于SpringBoot 来说可能注解的量会直线上升,比如

    @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) @EnableAutoConfiguration @ComponentScan(excludeFilters = {       @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),       @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

     

  4. 那么由于如上的问题带来了一个问题 可能一个简单的类中的代码比注解还要少!

  5. 我们通过组合注解的方式来解决此问题

    我们声明如下

    @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注解编程模型

https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model

对于Spring来说通常定义的注解是要适配原有的功能 比如Controller注解可以声明Bean的名称

但是一旦定义的组合注解的名称相同自然就会存在如下的问题【覆盖】

Spring提供了AliasFor注解来完成别名的转换 比如

@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 {      /**     * Exclude specific auto-configuration classes such that they will never be applied.     * @return the classes to exclude     */    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")    Class<?>[] exclude() default {};      /**     * Exclude specific auto-configuration class names such that they will never be     * applied.     * @return the class names to exclude     * @since 1.3.0     */    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")    String[] excludeName() default {};      /**     * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}     * for a type-safe alternative to String-based package names.     * @return base packages to scan     * @since 1.3.0     */    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")    String[] scanBasePackages() default {};      /**     * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to     * scan for annotated components. The package of each class specified will be scanned.     * <p>     * Consider creating a special no-op marker class or interface in each package that     * serves no purpose other than being referenced by this attribute.     * @return base packages to scan     * @since 1.3.0     */    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")    Class<?>[] scanBasePackageClasses() default {};   }

 

通过如上方式可以指定到元注解的属性【比如SpringBootApplication的scanBasePackageClasses   ===》ComponentScan的basePackageClasses】

本文发表于2017年11月27日 14:39
(c)注:本文转载自https://my.oschina.net/qixiaobo025/blog/1580315,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1171 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1