SpringBoot常用注解(1)

SpringBoot常用注解

@ComponentScan

扫描路径并装配

从定义的扫描路径中找出标识了需要装配的类自动装配到spring的bean容器中

我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。
注:所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    // 对应的包扫描路径 可以是单个路径,也可以是扫描的路径数组
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};
	// 指定具体的扫描的类
    Class<?>[] basePackageClasses() default {};
	// 对应的bean名称的生成器 默认的是BeanNameGenerator
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
	// 处理检测到的bean的scope范围
    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
	// 是否为检测到的组件生成代理
    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
	// 控制符合组件检测条件的类文件   默认是包扫描下的  **/*.class
    String resourcePattern() default "**/*.class";
	// 是否对带有@Component @Repository @Service @Controller注解的类开启检测,默认是开启的
    boolean useDefaultFilters() default true;
	/**
     * 指定某些定义Filter满足条件的组件 FilterType有5种类型如:
     *                                  ANNOTATION, 注解类型 默认
                                        ASSIGNABLE_TYPE,指定固定类
                                        ASPECTJ, ASPECTJ类型
                                        REGEX,正则表达式
                                        CUSTOM,自定义类型
     * @return
     */
    ComponentScan.Filter[] includeFilters() default {};
	// 排除某些过滤器扫描到的类
    ComponentScan.Filter[] excludeFilters() default {};
	// 扫描到的类是都开启懒加载 ,默认是不开启的
    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}

@Retention

确定生命周期

注解按生命周期来划分可分为3类:

1、RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
2、RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
3、RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;

这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码。

那怎么来选择合适的注解生命周期呢?

首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override@SuppressWarnings,则可选用 SOURCE 注解。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

----------------------------------------------
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    // 这种类型的Annotations只在源代码级别保留,编译时就会被忽略,在class字节码文件中不包含。
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    // 这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在但JVM将会忽略,运行时无法获得。
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    // 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
    RUNTIME
}

@Target

确定注解的使用范围

用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}

--------------------------------------------------------------------------
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    // 接口、类、枚举、注解
    TYPE,

    /** Field declaration (includes enum constants) */
    // 字段、枚举的常量
    FIELD,

    /** Method declaration */
    // 方法
    METHOD,

    /** Formal parameter declaration */
    // 参数
    PARAMETER,

    /** Constructor declaration */
    // 构造器
    CONSTRUCTOR,

    /** Local variable declaration */
    // 局部变量
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    // 注解
    ANNOTATION_TYPE,

    /** Package declaration */
    // 包
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    // 类型参数
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    // 能标注任何类型的名称
    TYPE_USE
}

@Document

将被包含在javadoc

https://www.cnblogs.com/springmorning/p/10261472.html

@Inherited

子类将继承该注解

注意:此注解只对注解标记的超类有效,对接口是无效的。

@AliasFor

为注解属性声明别名。

使用案例介绍:

1.把多个元注解的属性组合在一起形成新的注解

如我们熟知的@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 = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};

如上所示@SpringBootApplication并没有定义新的属性而是复用其他注解已有的注解属性并对其进行组合
形成新的注解从而到达到便捷的目的。这样的注解我们可以称之为复合注解。
所以在使用SpringBoot 时我们只需要@SpringBootApplication一个注解就能开启
自动配置,自动扫描的功能。
而不再需要使下面三个注解来达到同样的目的。
@Configuration
@ComponentSan
@EnnableAutoConfiguration

2.继承注解的功能

如@Controller,@Service,@Repository都继承了@Component的功能他们的基本作用和@Component完全一样都是标明某个类是Spring的Bean,需要Spring容器进行管理。

不同之处在于对Spring bean进行了归类,从而能对不同类型的Bean进行不同的处理。

@Service代码如下

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {

    @AliasFor(annotation = Component.class)
    String value() default "";

}

3.在同个注解中为同一个功能定义两个名称不一样的属性,那么这两个属性彼此互为别名
如@RequestMapping注解中的value和path它们两互为别名。如下所示:

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

    
    @AliasFor("value")
    String[] path() default {};

}

这么做的目的在于
1.更便捷
当我们只定义一个属性的时候往往可以省略属性名如:
@RequestMapping(“/user”)
2.顾名思义
当我门定义多个属性时为了能做到顾名思义
使之达到一目了然的效果我们需要选择一个更加贴合特定场景的名称。
@RequestMapping(path = “/user”,method = RequestMethod.GET)
当然你也可以这样:
@RequestMapping(value = “/user”,method = RequestMethod.GET)
只是这样子的定义value = “/user” 不能很准确地传达代码的意图。

https://www.jianshu.com/p/d6bba708100d

@Configuration

声明为配置类

如果不加此注解,可能会导致违反单例的设计原则

加上@Configuration注解主要是给我们的类加上了cglib代理。

https://blog.csdn.net/qq_41907991/article/details/106008651

https://blog.csdn.net/qiuz1024/article/details/100530260

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值