美文网首页Spring boot
Spring Boot 注解收集

Spring Boot 注解收集

作者: tuacy | 来源:发表于2019-09-16 19:00 被阅读0次

           Spring Boot使用过程中,经常需要和很多注解打交道。也是我们常说的注解编程。所以接下来我们对Spring Boot常用注解做一个简单的收集。

    一 配置类相关注解

           

    配置类相关注解 解释
    @SpringBootApplication 组合注解,由@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三者组成,我们一般把该注解添加在启动类上
    @ComponentScan 用于指定组件的扫描路径和过滤规则
    @EnableAutoConfiguration 启用自动配置,就是让@SpringBootConfiguration、@Configuration注解起作用
    @SpringBootConfiguration 标注当前类是配置类
    @Configuration 标注当前类是配置类
    @Bean 注解在方法上,一般在@Configuration注解类下使用,把方法返回的对象添加到Spring IOC容器里面去,并且容器里面Bean的名字就是方法名
    @Import 导入类,有时没有把某个类注入到IOC容器中,但在运用的时候需要获取该类对应的Bean,这个时候我们就可以使用@Import导入需要的Bean
    @AutoConfigureAfter 加载指定配置的类之后再加载当前类,一般和@Configuration一起出现
    @AutoConfigureBefore 加载指定配置的类之前加载当前类,一般和@Configuration一起出现
    @AutoConfigureOrder 指定配置类的加载顺序,一般和@Configuration一起出现

    1.1 @SpringBootApplication

    @Target(ElementType.TYPE) // 添加在类上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration //@SpringBootConfiguration
    @EnableAutoConfiguration // @EnableAutoConfiguration
    @ComponentScan(excludeFilters = { // @ComponentScan
            @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM,
                    classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
    
        /**
         * 排除特定的自动配置类 -- @EnableAutoConfiguration里面的功能
         */
        @AliasFor(annotation = EnableAutoConfiguration.class)
        Class<?>[] exclude() default {};
    
        /**
         * 排除特定的自动配置类名称 -- @EnableAutoConfiguration里面的功能
         */
        @AliasFor(annotation = EnableAutoConfiguration.class)
        String[] excludeName() default {};
    
        /**
         *
         * 在指定的包下扫描带组件注解的类 -- @ComponentScan里面的功能
         */
        @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
        String[] scanBasePackages() default {};
    
        /**
         * 指定类,会去扫描该类所在的包下面带有组件注解的类 -- @ComponentScan里面的功能
         */
        @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
        Class<?>[] scanBasePackageClasses() default {};
    
    }
    

           @SpringBootApplication是一个组合注解,由@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解组成.换言之加了@SpringBootApplication注解之后就把相应的三个注解的功能都加上了。Springboot提供了。简化程序的配置。@SpringBootApplication注解一般添加的启动了上。关于@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan我们会在下面讲到。

    1.2 @ComponentScan

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE) // 可以添加在类上
    @Documented
    @Repeatable(ComponentScans.class)
    public @interface ComponentScan {
    
        /**
         * scan对应的包路径(可以指定多个)
         */
        @AliasFor("basePackages")
        String[] value() default {};
        @AliasFor("value")
        String[] basePackages() default {};
    
        /**
         * 可以指定多个类或接口的class,扫描时会 在这些指定的类和接口所属的包进行扫面。
         */
        Class<?>[] basePackageClasses() default {};
    
        /**
         * 通过BeanNameGenerator来得到bean对应的名字,进而得到对应的Class
         */
        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 ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
    
        /**
         * 是否对带有@Component @Repository @Service @Controller注解的类开启检测,默认是开启的
         */
        boolean useDefaultFilters() default true;
    
        /**
         * 指定某些定义Filter满足条件的组件 FilterType有5种类型如:
         *  ANNOTATION, 注解类型 默认
         *  ASSIGNABLE_TYPE,指定固定类
         *  ASPECTJ, ASPECTJ类型
         *  REGEX,正则表达式
         *  CUSTOM,自定义类型
         *
         */
        Filter[] includeFilters() default {};
    
        /**
         * 排除某些过来器扫描到的类
         */
        Filter[] excludeFilters() default {};
    
        /**
         * 扫描到的类是都开启懒加载 ,默认是不开启的
         */
        boolean lazyInit() default false;
    
    }
    

           @ComponentScan做的事情就是告诉Spring从哪里找到Bean。@ComponentScan会默认去@SpringBootApplication注解的类所在的包及其下级包去扫描bean(就是去扫描添加了@Component、@Service、@Repository、@Controller),然后把他们添加到Spring IOC容器里面去。但是,有的时候有些包不在这个下面,这个时候我们就需要通过@ComponentScan显示的去指定要扫描的包名了。

    1.3 @EnableAutoConfiguration、@SpringBootConfiguration、@Configuration

    因为@EnableAutoConfiguration、@SpringBootConfiguration、@Configuration这三是一体的,所以咱们把他们归到一起来说明。

    1.3.1 @EnableAutoConfiguration

    @Target(ElementType.TYPE) // 组件添加在类上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class) // 帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器
    public @interface EnableAutoConfiguration {
    
        String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
        /**
         * 排除特定的自动配置类
         */
        Class<?>[] exclude() default {};
    
        /**
         *
         * 排除特定的自动配置类名称
         */
        String[] excludeName() default {};
    
    }
    

           @EnableAutoConfiguration注解使自动配置生效。用于帮助SpringBoot应用将所有符合条件的@SpringBootConfiguration、@Configuration配置加载到当前SpringBoot IOC容器里面去。换句话说,想使用@SpringBootConfiguration、@Configuration就得一定得使用@EnableAutoConfiguration注解。只有@EnableAutoConfiguration配合@SpringBootConfiguration、@Configuration共同作用下,才可以帮助Spring Boot把@SpringBootConfiguration、@Configuration修饰的类里面的Bean扫描出来,添加到Spring IOC容器里面去.

    按照我们常规的Spring Boot应用。我们一般会启动类上添加@SpringBootApplication注解。其实就已经加上了@EnableAutoConfiguration注解,因为@SpringBootApplication注解包括了@EnableAutoConfiguration注解。

    1.3.2 @SpringBootConfiguration、@Configuration

           @SpringBootConfiguration、@Configuration两个注解是一样的。用来标记配置类。

    @SpringBootConfiguration

    @Target(ElementType.TYPE) // 添加在类上的注解
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration
    public @interface SpringBootConfiguration {
    
    }
    

    @Configuration

    @Target(ElementType.TYPE) // 添加在类上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component // 也是一个组件
    public @interface Configuration {
    
        /**
         * Configuration注解的类也是一个组件,用于显示的指定在Spring容器里面组件的名称。
         * 如果没有显示指定就是类的名称并且首字母小写
         */
        @AliasFor(annotation = Component.class)
        String value() default "";
    
    }
    

           简单来说就是用@SpringBootConfiguration、@Configuration标注的类是配置类,同时在该类下面一般会包含一个或多个被@Bean注解的方法。这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描。加入到Spring IOC容器中。并且这些Bean的名称就是方法名。

    1.4 @Bean

    @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) // 一般添加在方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Bean {
    
        /**
         * 显示指定Bean对应的名字,如果没有指定则是对应的方法名字
         */
        @AliasFor("name")
        String[] value() default {};
    
        /**
         * 显示指定Bean对应的名字,如果没有指定则是对应的方法名字
         */
        @AliasFor("value")
        String[] name() default {};
    
        @Deprecated
        Autowire autowire() default Autowire.NO;
    
        /**
         * 用来表示当前bean是否可以被注入到其他实例中,依赖注入
         */
        boolean autowireCandidate() default true;
    
        /**
         * 构造方法执行完之后,执行的方法
         */
        String initMethod() default "";
    
        /**
         * 关闭应用程序上下文时在bean实例上调用的方法的可选名称
         */
        String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
    
    }
    

           @Bean是一个方法级别上的注解,主要用在@SpringBootConfiguration、@Configuration注解的配置类里面使用。Spring Boot会帮助把@Bean注解方法的对象添加到Spring IOC容器里面去,供我们在别的地方使用。

    1.4 @Import

    @Target(ElementType.TYPE) // 指明该注解是添加在类上的
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Import {
    
        /**
         * 需要import的类
         */
        Class<?>[] value();
    
    }
    

           @Import注解用于帮助把我们需要的类导入到组件类里面去,有时没有把某个类注入到Spring IOC容器中,但在某个类使用的时候需要获取该类对应的Bean,此时就需要用到@Import注解。

    1.5 控制配置类的加载顺序(@AutoConfigureAfter、@AutoConfigureBefore、@AutoConfigureOrder)

    @AutoConfigureAfter、@AutoConfigureBefore

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.TYPE }) // 一般用于添加在类上
    @Documented
    public @interface AutoConfigureAfter {
    
        /**
         * Class数组对应的类加载之后在加载
         */
        Class<?>[] value() default {};
    
        /**
         * 配置名称对应的配置类加载之后在加载
         */
        String[] name() default {};
    
    }
    

    @AutoConfigureOrder

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
    @Documented
    public @interface AutoConfigureOrder {
    
        int DEFAULT_ORDER = 0;
    
        /**
         * 加载顺序,值越小越先加载
         */
        int value() default DEFAULT_ORDER;
    
    }
    

           @AutoConfigureAfter、@AutoConfigureBefore、@AutoConfigureOrder三个注解用于控制配置类的加载顺序。而且非常重要的一点是这三个注解一定要配合spring.factory文件来一起使用,因为Spring只会对spring.factory文件下的配置类进行排序。所以我们需要在resources/META-INF/spring.factory文件里面写入需要排序的这些配置类的路径。

    二 Bean(组件)相关注解

    2.1 申明Bean相关的注解

           用于把一个类声明为Bean(组件)。这样Spring Boot启动的时候(注意@ComponentScan注解的使用)就会把这些Bean扫描出来添加到IOC容器里面去。

    申明Bean相关的注解 解释
    @Component 最普通的组件,可以被注入到Spring容器进行管理,通用注解
    @Service 作用于业务逻辑层的组件,只是标注该类处于业务逻辑层
    @Repository 作用于持久层(dao)的组件,并支持自动处理数据库操作产生的异常

    @Component、@Service、@Repository注解属性都是一样的

    @Target(ElementType.TYPE) //该注解一般用于添加在方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Indexed
    public @interface Component {
    
        /**
         * 组件对应的名字(获取组件的时候可以通过类型获取,也可以通过名字获取)
         */
        String value() default "";
    
    }
    

    关于@Repository的作用,这里特别说明下。因为原生java操作数据库所产生的异常只定义了几种,但是产生数据库异常的原因却有很多种,这样对于数据库操作的报错排查造成了一定的影响;而Spring拓展了原生的持久层异常,针对不同的产生原因有了更多的异常进行描述。所以,在注解了@Repository的类上如果数据库操作中抛出了异常,就能对其进行处理,转而抛出的是翻译后的spring专属数据库异常,方便我们对异常进行排查处理。

           关于@Component、@Service、@Repository的使用,最终只有一个目的,希望咱们一看到@Repository就知道这个是数据库Dao层的代码,一看到@Service注解就知道是业务层的代码。

    2.2 Bean属性相关注解

           

    Bean属性相关注解 解释
    @Scope 设置Spring容器如何新建Bean实例,一般配合@Bean、@Component、@Service、@Repository一起使用
    @PostConstruct 在构造函数执行完之后执行
    @PreDestory 在Bean销毁之前执行

    2.2.1 @Scope

    @Target({ElementType.TYPE, ElementType.METHOD}) // 一般用来添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Scope {
    
        /**
         * Alias for {@link #scopeName}.
         * @see #scopeName
         */
        @AliasFor("scopeName")
        String value() default "";
    
        /**
         *
         * 指定要用于带注释的组件/ bean的作用域的名称
         *  可以设置下面四种值
         *  - ConfigurableBeanFactory.SCOPE_PROTOTYPE: 每次依赖注入时,都会产生新的对象
         *  - ConfigurableBeanFactory.SCOPE_SINGLETON: 单例模式,在整个应用中只能创建一个实例
         *  - org.springframework.web.context.WebApplicationContext.SCOPE_REQUEST: 在一个请求中创建一个实例
         *  - org.springframework.web.context.WebApplicationContext.SCOPE_SESSION: 每次创建一个会话中创建一个实例
         */
        @AliasFor("value")
        String scopeName() default "";
    
        /**
         * 指定是否应将组件配置为作用域代理
         * 可以设置为下面几种值
         * - ScopedProxyMode.DEFAULT:等同于ScopedProxyMode.NO
         * - ScopedProxyMode.NO:(默认)不进行代理
         * - ScopedProxyMode.INTERFACES:创建一个JDK代理模式
         * - ScopedProxyMode.TARGET_CLASS:基于类的代理模式
         */
        ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
    
    }
    

          Scope字面意思是范围,标志一个注入器/对象的使用范围,很多文章说成生命周期也是可以的。比如,单例模式,局部单例模式等等。@Scope注解就是用来声明一个Bean的生命周期(作用域)。

          @Scope实际使用的时候一般是添加在@Bean修饰的方法上的。比如如下的实例。

    @Configuration
    public class ZkConfiguration {
    
        @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) // 只有一个实例
        @Bean(initMethod = "init", destroyMethod = "stop")
        public ZkClient zkClient() {
            return new ZkClient();
        }
    
    
    }
    

    2.2.2 @PostConstruct

    @Documented
    @Retention (RUNTIME)
    @Target(METHOD)
    public @interface PostConstruct {
    }
    

           @PostConstruct用来修饰一个分静态并且返回void的方法。该方法只会在构造函数之后执行一次。@PostConstruct一般@Component、@Service、@Repository修饰的对象里面使用。

    2.2.3 @PreDestory

    @Documented
    @Retention (RUNTIME)
    @Target(METHOD)
    public @interface PreDestroy {
    }
    

           @PreDestroy也是用来修饰一个分静态并且返回void的方法。该方法只会在对象函数之后执行一次。@PreDestory和一样@PostConstruct一般也是在@Component、@Service、@Repository修饰的对象里面使用。

    2.3 Bean注入相关注解

           注入注解就是帮助我们自动引入依赖的对象。

    Bean注入相关注解 解释
    @Autowired 先按类型注入,然后按照名称注入,都无法找到唯一的一个实现类则报错
    @Inject 在Spring的环境下,@Inject和@Autowired是相同的
    @Resource 先按名字注入,再按类型注入,都无法找到唯一的一个出现异常
    @Qualifier 用于指定Bean的名字,一般配合用来配合@Autowired使用

    2.3.1 @Autowired

    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Autowired {
    
        /**
         * 申明当前对象是否是必须的
         */
        boolean required() default true;
    
    }
    

           @Autowired Spring提供的工具(由Spring的依赖注入工具(BeanPostProcessor、BeanFactoryPostProcessor)自动注入Bean。它可以对类成员变量、方法及构造函数进行标注。 通过 @Autowired的使用来消除 set ,get方法。@Autowired先通过类型去Spring IOC容器里面查找对象,如果没有查找到再按照Bean名称去查找。如果无法找到唯一的Bean并且Bean是必须的则抛出异常。(可以看下@Qualifier的用法)

    2.3.2 @Inject

           在Spring的环境下,@Inject和@Autowired是相同的。

    2.3.3 @Resource

    @Target({TYPE, FIELD, METHOD}) // 添加在变量或者方法上
    @Retention(RUNTIME)
    public @interface Resource {
        /**
         * 资源的JNDI名称
         */
        String name() default "";
    
        /**
         * 引用指向它的资源的名称可以使用全局JNDI名称链接到任何兼容的资源
         */
    
        String lookup() default "";
    
        /**
         * Bean对应的类型
         */
        Class<?> type() default java.lang.Object.class;
    
        /**
         * 资源的两种可能的身份验证类型
         */
        enum AuthenticationType {
            CONTAINER,
            APPLICATION
        }
    
        /**
         * 用于此资源的身份验证类型。
         */
        AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
    
        /**
         * 指示是否可以在此组件与其他组件之间共享此资源。
         */
        boolean shareable() default true;
    
        /**
         * 此资源应映射到的产品特定名称
         */
        String mappedName() default "";
    
        /**
         * 此资源的描述
         */
        String description() default "";
    }
    

           @Resource有两个重要属性:name、type。@Resource和@Autowired的区别在于。@Resource先通过Bean名字去容器里面查找,如果没找到在通过类型去容器里面查找。

    2.3.4 @Qualifier

    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Qualifier {
    
        /**
         * 注解对应的名字
         */
        String value() default "";
    
    }
    

           可能会有这样一种情况,当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,我们可以使用@Qualifier注释和@Autowired注释通过指定哪一个真正的bean将会被装配来消除混乱。比如如下的代码。

        private ProductInfo productInfo;
    
        @Autowired
        @Qualifier(value = "productInfo")
        public void setProductInfo(ProductInfo productInfo) {
            this.productInfo = productInfo;
        }
    

    2.4 Bean延时加载注解(@Lazy)

    @Lazy

    @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Lazy {
    
        /**
         * 是否懒加载
         */
        boolean value() default true;
    
    }
    

           @Lazy:用于标识Bean是否需要延迟加载,延时加载就是在第一次使用的时候才加载。@Lazy的主要作用就是用来减少Spring IOC容器启动的加载时间。

    2.5 Bean依赖注解(@DependsOn)

    @DependsOn

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface DependsOn {
    
        /**
         * 依赖的Bean对应的名称
         */
        String[] value() default {};
    
    }
    

          @DependsOn:控制Bean加载顺序。指定先加载@DependsOn对应的Bean。

    三 读取配置文件(.properties、.yam)相关注解

           读取配置文件相关的注解,就是用来帮助我们获取到配置文件.properties、.yam里面信息的。

    读取配置文件相关注解 解释
    @EnableConfigurationProperties 让使用@ConfigurationProperties注解的类生效
    @ConfigurationProperties 读取配置文件的信息,并自动封装成实体类
    @PropertySource 指定的属性文件(只能加载*.properties文件,不能加载yaml文件)映射到对象
    @ImportResource 导入Spring的*.xml配置文件,让xml配置文件里面的内容生效

    3.1 @EnableConfigurationProperties

    @Target(ElementType.TYPE) // 添加在类上的注解
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(EnableConfigurationPropertiesImportSelector.class)
    public @interface EnableConfigurationProperties {
    
        /**
         * 对应于添加了@ConfigurationProperties的类,让他们生效
         */
        Class<?>[] value() default {};
    
    }
    

           @EnableConfigurationProperties注解的作用是让使用@ConfigurationProperties注解的类生效。你可以通过在@EnableConfigurationProperties注解中直接简单的列出属性类来快捷的注册@ConfigurationProperties bean的定义。而且@EnableConfigurationProperties我们一般添加在Applicaiton类上面。

    3.2 @ConfigurationProperties

    @Target({ ElementType.TYPE, ElementType.METHOD }) // 添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ConfigurationProperties {
    
        /**
         * 属性前缀
         */
        @AliasFor("prefix")
        String value() default "";
        @AliasFor("value")
        String prefix() default "";
    
        /**
         * 是否忽视无效的字段
         */
        boolean ignoreInvalidFields() default false;
    
        /**
         * 是否忽视未知字段
         */
        boolean ignoreUnknownFields() default true;
    
    }
    

           有时候有这样子的情景,我们想把配置文件的信息,读取并自动封装成实体类,这样子,这时候,我们就可以使用@ConfigurationProperties注解,它可以把同类的配置信息自动封装成实体类。

           我们用一个简单的实例来说明,比如我们在application.yml里面添加一些自定义的属性。我们就可以通过@ConfigurationProperties注解来获取到这些属性值

    application.yml文件里面添加

    
    # 自定义的一些属性
    user:
      info:
        name: tuacy
        age: 27
    

    把这些属性映射到实体类

    @ConfigurationProperties(prefix = "user.info")
    public class UserInfo {
    
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    

          最后在Application类上添加@EnableConfigurationProperties(value = {UserInfo.class})。这样就把配置文件里面的数据都映射到UserInfo类上去了,并且UserInfo类已经添加到了Spring IOC容器里面去了。

    3.3 @PropertySource

    @Target(ElementType.TYPE) // 该注解添加在类上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Repeatable(PropertySources.class)
    public @interface PropertySource {
    
        /**
         * 指示此属性源的名称。如果省略,将根据底层资源的描述生成名称
         */
        String name() default "";
    
        /**
         * 指示要加载的属性文件的资源位置
         * 例如,value = "classpath:product.properties"。则表示resource目录下的product.properties文件
         */
        String[] value();
    
        /**
         * 指示是否应忽略找不到属性资源的错误
         */
        boolean ignoreResourceNotFound() default false;
    
        /**
         * 编码格式
         * 例如,"UTF-8"
         */
        String encoding() default "";
    
        /**
         * 只是怎么去解析属性对应的值,比如如果想把 yyyy-mm 转换成Date
         * @see org.springframework.core.io.support.DefaultPropertySourceFactory
         * @see org.springframework.core.io.support.ResourcePropertySource
         */
        Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
    
    }
    

           @PropertySource注解的作用是加载指定的属性文件(配置文件),把配置文件映射到对象。只能加载*.properties文件,不能加载yaml文件。@PropertySource一般配合@Value一起使用。

           关于@PropertySource注解使用的一个简单的实例。

    resource目录下product.properties文件内容(配置文件)

    # 自定义配置信息
    ppid = 1000
    mmid = 1
    ccid = 10
    

    配置文件映射到Bean

    /**
     * 注入resource下product.properties文件里面的信息
     */
    @Configuration
    @PropertySource(value = "classpath:product.properties", encoding = "utf-8")
    public class ProductInfo {
    
        @Value("${ppid}")
        private int pid;
    
    
        @Value("${mmid}")
        private int mid;
    
    
        @Value("${ccid}")
        private int cid;
    
        public int getPid() {
            return pid;
        }
    
        public void setPid(int pid) {
            this.pid = pid;
        }
    
        public int getMid() {
            return mid;
        }
    
        public void setMid(int mid) {
            this.mid = mid;
        }
    
        public int getCid() {
            return cid;
        }
    
        public void setCid(int cid) {
            this.cid = cid;
        }
    }
    

    3.4 @ImportResource

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE) // 该注解只能添加在类上(我们一般把他添加在主配置类上)
    @Documented
    public @interface ImportResource {
    
        /**
         * xml配置文件对应的位置
         */
        @AliasFor("locations")
        String[] value() default {};
        @AliasFor("value")
        String[] locations() default {};
    
        /**
         *
         * 处理通过属性指定的资源时使用的实现
         */
        Class<? extends BeanDefinitionReader> reader() default BeanDefinitionReader.class;
    
    }
    

           导入Spring的xml配置文件,让xml配置文件里面的内容生效。SpringBoot中编写的Spring配置文件是不能自动识别的。(相当于把Bean放到xml配置文件里面去定义了。随着Spring Boot的使用这种方式会越来越少,因为现在大部分都是通过@Configuration来配置的)。

    四 @Value注解

    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Value {
    
        /**
         *
         * 实际值表达式
         * 例如,{@code #{systemProperties.myProp}}.
         */
        String value();
    
    }
    

           @Value注解用于将外部的值动态注入到Bean中,大概有如下这么几种情况:

    4.1 注入普通字符串

        /**
         * 注入普通字符串,相当于private String normal = "normal"
         */
        @Value("normal")
        private String normal;
    

    4.2 注入操作系统属性

        /**
         * 注入操作系统属性
         */
        @Value("#{systemProperties['os.name']}")
        private String systemPropertiesName;
    

    4.3 注入表达式结果

        /**
         * 注入表达式结果,相当于 double randomNumber = java.lang.Math).random() * 100.0
         */
        @Value("#{ T(java.lang.Math).random() * 100.0 }")
        private double randomNumber;
    

    4.4 注入其他Bean属性

        /**
         * 注入其他Bean属性:相当于把IOC容器里面valueInject名字对应的对象的name属性赋值给变量
         */
        @Value("#{valueInject.name}")
        private String fromAnotherBean;
    

    4.5 注入文件资源

        /**
         * 注入文件资源,相当于把resource目录下valueInjectConfig.txt文件注入进来
         */
        @Value("classpath:valueInjectConfig.txt")
        private Resource valueInjectConfig;
    

    4.6 注入URL资源

        /**
         * 注入URL资源,相当于把http://www.baidu.com对应的资源注入进来
         */
        @Value("http://www.baidu.com")
        private Resource baiduUrl;
    

    4.7 注入配置文件信息

           比如如下的例子我们加载product.properties文件里面的信息(我们也可以加载application.yml文件里面的信息,加载application.yml文件信息的时候可以不加@PropertySource指定路径)

    resource目录下product.properties文件信息

    # 自定义配置信息
    ppid = 1000
    mmid = 1
    ccid = 10
    

    @Value注入

    /**
     * 注入resource下product.properties文件里面的信息
     */
    @Configuration
    @PropertySource(value = "classpath:product.properties", encoding = "utf-8")
    public class ProductInfo {
    
        @Value("${ppid}")
        private int pid;
    
    
        @Value("${mmid}")
        private int mid;
    
    
        @Value("${ccid}")
        private int cid;
    
        public int getPid() {
            return pid;
        }
    
        public void setPid(int pid) {
            this.pid = pid;
        }
    
        public int getMid() {
            return mid;
        }
    
        public void setMid(int mid) {
            this.mid = mid;
        }
    
        public int getCid() {
            return cid;
        }
    
        public void setCid(int cid) {
            this.cid = cid;
        }
    }
    

    五 环境切换相关注解

           环境切换注解说白了就是做到不同的环境注入不同的Bean。比如常见的有开发环境和测试环境用的数据库配置不一样。

    环境切换相关注解 解释
    @Profile 通过设定Environment的ActiveProfiles来设定当前Bean是否要添加到Spring IOC容器里面去
    @Conditional 按照一定的条件进行判断,满足条件给添加到Spring IOC容器里面去

    5.1 @Profiles

    @Target({ElementType.TYPE, ElementType.METHOD}) // 该注解用于添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Conditional(ProfileCondition.class)
    public @interface Profile {
    
        /**
         * profile对应的名字。比如生成环境有一个名字,测试环境有一个名字
         */
        String[] value();
    
    }
    

          @Profiles可以实现不同环境(开发、测试、部署等)使用不同的配置。任何@Component或@Configuration都能被@Profile标记,从而限制加载它的时机。

    5.2 @Conditional

    @Target({ElementType.TYPE, ElementType.METHOD}) // 常用于添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Conditional {
    
        /**
         * 继承Condition接口的Class数组
         * 当所有的Class的matches方法都返回true的时候,才满足条件
         */
        Class<? extends Condition>[] value();
    
    }
    

          @Conditional注解会按照一定的条件进行判断,满足条件给容器注册bean。

    六 条件注解

    条件注解 解释
    @ConditionalOnClass classpath中存在该类时起效
    @ConditionalOnMissingClass classpath中不存在该类时起效
    @ConditionalOnBean Spring IOC容器中存在该类型Bean时起效
    @ConditionalOnMissingBean Spring IOC容器中不存在该类型Bean时起效
    @ConditionalOnSingleCandidate DI容器中该类型Bean只有一个或@Primary的只有一个时起效
    @ConditionalOnExpression SpEL表达式结果为true时
    @ConditionalOnProperty 参数设置或者值一致时起效
    @ConditionalOnResource 指定的文件存在时起效
    @ConditionalOnJndi 指定的JNDI存在时起效
    @ConditionalOnJava 指定的Java版本存在时起效
    @ConditionalOnWebApplication Web应用环境下起效
    @ConditionalOnNotWebApplication 非Web应用环境下起效

           所有的这些条件注解一般和声明Bean的一些注解(@Bean、@Component、@Service、@Repository)同时出现。来控制Bean是否生成。

    七 切面AOP相关注解

    切面AOP相关注解 解释
    @Aspect 声明一个切面,只是一个标识作用
    @PointCut 声明切点,在java配置类中使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持
    @Around 在方法执行之前与之后执行
    @Before 在方法执行之前执行
    @After 在方法执行之后执行
    @AfterReturning 方法正常退出的时候执行
    @AfterThrowing 方法有异常抛出的时候执行

    7.1 @Aspect

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE) // 添加在方法上
    public @interface Aspect {
    
        /**
         * @return the per clause expression, defaults to singleton aspect.
         * Valid values are "" (singleton), "perthis(...)", etc
         */
        public String value() default "";
    }
    

           @Aspect注解的作用是把当前类标识为一个切面供Spring容器读取。@Aspect注解只是一个标识作用。

    7.2 @PointCut

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD) // 添加在方法上面
    public @interface Pointcut {
    
        /**
         * 切入点表达式
         */
        String value() default "";
    
        /**
         * 指定命名切入点方法参数列表参数名字,
         * 可以有多个用“,”分隔,这些参数将传递给通知方法同名的参数,
         * 同时比如切入点表达式“args(param)”将匹配参数类型为命名切入点方法同名参数指定的参数类型。
         */
        String argNames() default "";
    }
    

           @Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。

    7.3 @Around

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD) // 注解用于添加在方法上
    public @interface Around {
    
        /**
         * 切入点表达式,一般配合@Pointcut一起使用
         */
        String value();
    
        /**
         * 用来接收AspectJ表达式中的参数
         */
        String argNames() default "";
    
    }
    

           @Around环绕增强,方法执行前和执行后都会执行。

    7.4 @Before

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Before {
    
        /**
         * 切入点表达式,一般配合@Pointcut一起使用
         */
        String value();
    
        /**
         * 用来接收AspectJ表达式中的参数
         */
        String argNames() default "";
    
    }
    

           @Before方法执行前执行。

    7.5 @After

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface After {
    
        /**
         * 切入点表达式,一般配合@Pointcut一起使用
         */
        String value();
    
        /**
         * 用来接收AspectJ表达式中的参数
         */
        String argNames() default "";
    
    }
    

           @After方法执行后执行。

    7.6 @AfterReturning

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface AfterReturning {
    
        /**
         * 切入点表达式,一般配合@Pointcut一起使用
         */
        String value() default "";
    
        /**
         * 切入点表达式,一般配合@Pointcut一起使用,指定时覆盖 "value" 
         */
        String pointcut() default "";
    
        /**
         * 用于绑定返回值的参数的名称
         */
        String returning() default "";
    
        /**
         * 用来接收AspectJ表达式中的参数
         */
        String argNames() default "";
    
    }
    

           @AfterReturning方法正常退出的时候执行。

    7.7 @AfterThrowing

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface AfterThrowing {
    
        /**
         * 切入点表达式,一般配合@Pointcut一起使用
         */
        String value() default "";
    
        /**
         * 切入点表达式,一般配合@Pointcut一起使用,指定时覆盖 "value"
         */
        String pointcut() default "";
    
        /**
         * 用于绑定抛出异常的参数的名称
         */
        String throwing() default "";
    
        /**
         * 用来接收AspectJ表达式中的参数
         */
        String argNames() default "";
    
    }
    

           @AfterThrowing方法抛出异常的时候执行。

    八 事件监听注解(@EventListener)

    @EventListener

    @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) // 添加在方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface EventListener {
    
        /**
         * 此侦听器处理的事件类。具体可以参考ApplicationEvent的用法
         */
        @AliasFor("classes")
        Class<?>[] value() default {};
        @AliasFor("value")
        Class<?>[] classes() default {};
    
        /**
         * 用来定义所侦听事件是否处理的前置条件,这里需要注意的是使用 Spring Expression Language (SpEL)定义条件
         * condition可以实现更加精细的事件监听
         *
         *  比如如下的例子,监听CustomEvent里面messageEntity对象的code的属性为‘oKong’的事件
         *  @EventListener(condition = "#customEvent.messageEntity.code == 'oKong'")
         *  public void handleCustomEventByCondition(CustomEvent customEvent) {
         *      //TODO:
         *  }
         */
        String condition() default "";
    
    }
    

           @EventListener修饰在方法上。用于监听Spring事件。更加具体的用法可以参考ApplicationListener的使用。

    七 异步注解

    异步注解 解释
    @EnableAsync 开启异步方法的支持
    @Async 异步方法

    7.1 @EnableAsync

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AsyncConfigurationSelector.class)
    public @interface EnableAsync {
    
        /**
         * 指示要在类或方法级别检测的“异步”注释类型,默认是@Async
         */
        Class<? extends Annotation> annotation() default Annotation.class;
    
        /**
         * 当AdviceModemode为PROXY时,选择代理是基于接口实现还是cglib实现
         */
        boolean proxyTargetClass() default false;
    
        /**
         * 代理方式是由JDK实现还是AspectJ实现
         */
        AdviceMode mode() default AdviceMode.PROXY;
    
        /**
         *
         * 指示AsyncAnnotationBeanPostProcessors的顺序
         * 默认值是 Ordered.LOWEST_PRECEDENCE,为了在所有其他后处理器之后运行
         */
        int order() default Ordered.LOWEST_PRECEDENCE;
    
    }
    

          @EnableAsync用于开启异步方法的支持。只有开启了异步方法的支持才可以使用@Async。

    7.2 @Async

    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Async {
    
        /**
         *
         * 指定异步操作的限定符值。
         */
        String value() default "";
    
    }
    

          @Async可以把某一个方法或者类下面的方法全部变成异步处理的方法。

    八 定时任务相关注解

           

    定时任务相关注解 解释
    @EnableScheduling 在配置类上使用,开启计划任务的支持
    @Scheduled 来申明这是一个任务,包括cron,fixDelay,fixRate等类型

    8.1 @EnableScheduling

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Import(SchedulingConfiguration.class)
    @Documented
    public @interface EnableScheduling {
    
    }
    

           @EnableScheduling注解用于开启定时任务的支持。简单来说就是如果我们想在应用里面使用@Scheduled就需要添加@EnableScheduling注解。一般添加在主配置类上。

    8.2 @Scheduled

    @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Repeatable(Schedules.class)
    public @interface Scheduled {
    
        /**
         * cron表达式
         */
        String cron() default "";
    
        /**
         * 时区
         * java.util.TimeZone#ID。cron表达式会基于该时区解析
         */
        String zone() default "";
    
        /**
         * 上一次执行完毕时间点之后多长时间再执行
         * @Scheduled(fixedDelay = 5000) //上一次执行完毕时间点之后5秒再执行
         */
        long fixedDelay() default -1;
    
        /**
         * 与fixedDelay意思相同,只是使用字符串的形式。唯一不同的是支持占位符
         * @Scheduled(fixedDelayString = "5000") //上一次执行完毕时间点之后5秒再执行
         */
        String fixedDelayString() default "";
    
        /**
         * 上一次开始执行时间点之后多长时间再执行
         * @Scheduled(fixedRate = 5000) //上一次开始执行时间点之后5秒再执行
         */
        long fixedRate() default -1;
    
        /**
         * 与fixedRate意思相同,只是使用字符串的形式
         */
        String fixedRateString() default "";
    
        /**
         * 第一次延迟多长时间后再执行
         */
        long initialDelay() default -1;
    
        /**
         * 与initialDelay意思相同,只是使用字符串的形式
         */
        String initialDelayString() default "";
    
    }
    

           @Scheduled用于定义一个定时任务。Spring会帮我们去解析这个定时任务,并且按照我们设置的时间去执行这个任务。

    九 事务相关注解

    事务相关注解 解释
    @EnableTransactionManagement 开启注解式事务的支持
    @Transactional 控制事务注解

    9.1 @EnableTransactionManagement

    @Target(ElementType.TYPE) // 该注解用于添加在类上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(TransactionManagementConfigurationSelector.class)
    public @interface EnableTransactionManagement {
    
        /**
         * 当AdviceModemode为PROXY时,选择代理是基于接口实现还是cglib实现
         */
        boolean proxyTargetClass() default false;
    
        /**
         * 代理方式是由JDK实现还是AspectJ实现
         */
        AdviceMode mode() default AdviceMode.PROXY;
    
        /**
         *
         * 指示AsyncAnnotationBeanPostProcessors的顺序
         * 默认值是 Ordered.LOWEST_PRECEDENCE,为了在所有其他后处理器之后运行
         */
        int order() default Ordered.LOWEST_PRECEDENCE;
    
    }
    

           @EnableTransactionManagement用于开启事务的支持,我们一般在主配置类上添加该注解。

    9.2 @Transactional

    @Target({ElementType.METHOD, ElementType.TYPE}) // 添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Transactional {
    
        /**
         * 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器。
         */
        @AliasFor("transactionManager")
        String value() default "";
    
        /**
         * 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器。
         */
        @AliasFor("value")
        String transactionManager() default "";
    
        /**
         * 事务的传播行为,默认值为 REQUIRED
         * 默认 Propagation.REQUIRED
         */
        Propagation propagation() default Propagation.REQUIRED;
    
        /**
         * 事务的隔离度,默认值采用 DEFAULT
         */
        Isolation isolation() default Isolation.DEFAULT;
    
        /**
         * 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务
         */
        int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
    
        /**
         * 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
         */
        boolean readOnly() default false;
    
        /**
         * 用于指定能够触发事务回滚的异常类型,
         */
        Class<? extends Throwable>[] rollbackFor() default {};
        String[] rollbackForClassName() default {};
    
        /**
         * 抛出 no-rollback-for 指定的异常类型,不回滚事务。
         */
        Class<? extends Throwable>[] noRollbackFor() default {};
        String[] noRollbackForClassName() default {};
    
    }
    

           @Transactional注解我们一般添加在Dao层的方法上面。当数据库操作异常的时候回滚。

    十 缓存相关注解

    缓存相关注解 解释
    @EnableCaching 开启缓存注解的支持
    @CacheConfig 用于统一制定一些配置参数,这样在其他缓存注解里面就不用重复指定
    @Cacheable 如果之前已经有缓存数据值直接返回缓存数据,否则执行方法,缓存方法的返回结果
    @CachePut 能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
    @CacheEvict 能够根据一定的条件对缓存进行清空
    @Caching 组合多个Cache注解的使用

    10.1 @EnableCaching

    @Target(ElementType.TYPE) // 该注解一般用于添加类上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(CachingConfigurationSelector.class)
    public @interface EnableCaching {
    
        /**
         * 当AdviceModemode为PROXY时,选择代理是基于接口实现还是cglib实现
         */
        boolean proxyTargetClass() default false;
    
        /**
         * 代理方式是由JDK实现还是AspectJ实现
         */
        AdviceMode mode() default AdviceMode.PROXY;
    
        /**
         *
         * 指示AsyncAnnotationBeanPostProcessors的顺序
         * 默认值是 Ordered.LOWEST_PRECEDENCE,为了在所有其他后处理器之后运行
         */
        int order() default Ordered.LOWEST_PRECEDENCE;
    
    }
    

           @EnableCaching注解用于开启缓存的支持,只有开启了缓存的支持,才有后续的@Cacheable、@Caching、@CacheEvict、@CachePut、@CacheConfig的使用。

    10.2 @CacheConfig

    @Target(ElementType.TYPE) // 该注解常用于添加在类上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface CacheConfig {
    
        /**
         * 缓存的名称,必须至少指定一个,我们可以简单的认为是命名空间。我们一般用项目的名字
         */
        String[] cacheNames() default {};
    
        /**
         * key生成器,可以实现 org.springframework.cache.interceptor.KeyGenerator接口,来规定想要保存的key的格式
         * 设置自定义的key生成器实现类对应Bean的名字
         */
        String keyGenerator() default "";
    
        /**
         * 缓存管理器,我们可以实现CacheManager接口来实现缓存管理器
         * 指定自定义的缓存管理器对应的Bean名称
         */
        String cacheManager() default "";
    
        /**
         * Cache解析器,用于根据实际情况来动态解析使用哪个Cache,实现CacheResolver接口
         * 指定自定义的Cache解析器对应的Bean名称
         */
        String cacheResolver() default "";
    
    }
    

          当我们需要缓存的地方越来越多,这个时候我们可以使用@CacheConfig注解来统一制定一些参数。这样在@Cacheable、@CachePut等这些注解上就可以不用重复去填这些参数了。

    10.3 @Cacheable

    @Target({ElementType.METHOD, ElementType.TYPE}) // 该注解用于添加在方法或者类上
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Cacheable {
    
        /**
         * 缓存的名称,必须至少指定一个,缓存的名称,必须至少指定一个,我们可以简单的认为是命名空间。我们一般用项目的名字
         */
        @AliasFor("cacheNames")
        String[] value() default {};
        @AliasFor("value")
        String[] cacheNames() default {};
    
        /**
         * 缓存的key
         */
        String key() default "";
    
        /**
         * key生成器,可以实现 org.springframework.cache.interceptor.KeyGenerator接口,来规定想要保存的key的格式
         * 设置自定义的key生成器实现类对应Bean的名字
         */
        String keyGenerator() default "";
    
        /**
         * 缓存管理器,我们可以实现CacheManager接口来实现缓存管理器
         * 指定自定义的缓存管理器对应的Bean名称
         */
        String cacheManager() default "";
    
        /**
         * Cache解析器,用于根据实际情况来动态解析使用哪个Cache,实现CacheResolver接口
         * 指定自定义的Cache解析器对应的Bean名称
         */
        String cacheResolver() default "";
    
        /**
         * 缓存的条件
         */
        String condition() default "";
    
        /**
         * 否定缓存。当条件结果为TRUE时,就不会缓存
         * @Cacheable(value=”testcache”,unless=”#userName.length()>2”)
         */
        String unless() default "";
    
        /**
         * 是否使用异步模式
         */
        boolean sync() default false;
    
    }
    

           @Cacheable注解会先查询是否已经有缓存,有会使用缓存,没有则会执行方法并缓存。

    10.4 @CachePut

    @Target({ElementType.METHOD, ElementType.TYPE}) // 添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface CachePut {
    
        /**
         * 缓存的名称,必须至少指定一个,我们可以简单的认为是命名空间。我们一般用项目的名字
         */
        @AliasFor("cacheNames")
        String[] value() default {};
        @AliasFor("value")
        String[] cacheNames() default {};
    
        /**
         * 缓存的key
         */
        String key() default "";
    
        /**
         * key生成器,可以实现 org.springframework.cache.interceptor.KeyGenerator接口,来规定想要保存的key的格式
         * 设置自定义的key生成器实现类对应Bean的名字
         */
        String keyGenerator() default "";
    
        /**
         * 缓存管理器,我们可以实现CacheManager接口来实现缓存管理器
         * 指定自定义的缓存管理器对应的Bean名称
         */
        String cacheManager() default "";
    
        /**
         * Cache解析器,用于根据实际情况来动态解析使用哪个Cache,实现CacheResolver接口
         * 指定自定义的Cache解析器对应的Bean名称
         */
        String cacheResolver() default "";
    
        /**
         * 缓存的条件
         */
        String condition() default "";
    
        /**
         * 否定缓存。当条件结果为TRUE时,就不会缓存
         * @Cacheable(value=”testcache”,unless=”#userName.length()>2”)
         */
        String unless() default "";
    
    }
    

          @CachePut注解的作用主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和@Cacheable不同的是,它每次都会触发真实方法的调用 。简单来说就是用户更新缓存数据。但需要注意的是该注解的value 和 key 必须与要更新的缓存相同,也就是与@Cacheable相同。

    10.5 @CacheEvict

    @Target({ElementType.METHOD, ElementType.TYPE}) // 添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface CacheEvict {
    
        /**
         * 缓存的名称,必须至少指定一个,我们可以简单的认为是命名空间。我们一般用项目的名字
         */
        @AliasFor("cacheNames")
        String[] value() default {};
        @AliasFor("value")
        String[] cacheNames() default {};
    
        /**
         * 缓存的key
         */
        String key() default "";
    
        /**
         * key生成器,可以实现 org.springframework.cache.interceptor.KeyGenerator接口,来规定想要保存的key的格式
         * 设置自定义的key生成器实现类对应Bean的名字
         */
        String keyGenerator() default "";
    
        /**
         * 缓存管理器,我们可以实现CacheManager接口来实现缓存管理器
         * 指定自定义的缓存管理器对应的Bean名称
         */
        String cacheManager() default "";
    
        /**
         * Cache解析器,用于根据实际情况来动态解析使用哪个Cache,实现CacheResolver接口
         * 指定自定义的Cache解析器对应的Bean名称
         */
        String cacheResolver() default "";
    
        /**
         * 缓存的条件
         */
        String condition() default "";
    
        /**
         * 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存
         */
        boolean allEntries() default false;
    
        /**
         * 是否在方法执行前就清空,缺省为 false,
         * 如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存
         */
        boolean beforeInvocation() default false;
    
    }
    

          @CacheEvict能够根据一定的条件对缓存进行清空。

    10.6 @Caching

    @Target({ElementType.METHOD, ElementType.TYPE}) // 添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Caching {
    
        Cacheable[] cacheable() default {};
    
        CachePut[] put() default {};
    
        CacheEvict[] evict() default {};
    
    }
    

          @Caching用于组合多个Cache注解的使用。相当于在一个方法上面添加多个注解。

    关于Spring Boot缓存这部分的内容,咱们可以试着去整合redis或者ehcache来使用。

    十一 Spring MVC相关注解

           

    Spring MVC相关注解 解释
    @Controller 声明该类为SpringMVC中的Controller,用来处理http请求
    @RestController 组合注解,@Controller + @ResponseBody.意味着,该Controller的所有方法都默认加上了@ResponseBody
    @RequestMapping 把htt请求映射到方法上去
    @PathVariable 用于接收路径参数,比如@RequestMapping(“/hello/{name}”)申明的路径,将注解放在参数中前,即可获取该值,通常作为Restful的接口实现方法
    @RequestParam 将请求参数绑定至方法参数
    @RequestBody 用于读取Request请求的body部分数据
    @ResponseBody 将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区
    @ModelAttribute 主要作用是绑定request或是form参数到模型(Model)
    @InitBinder 用来设置WebDataBinder,WebDataBinder用来自动绑定前台请求参数到Model中
    @ExceptionHandler 用于全局处理控制器里的异常
    @ControllerAdvice 通过该注解,我们可以将对于控制器的全局配置放置在同一个位置,和@Controller对应
    @RestControllerAdvice 同上和@RestController对应

    11.1 @Controller

    @Target({ElementType.TYPE}) // 该注解用于添加在方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Controller {
    
        /**
         * 用于显示指定组件的名称
         * @Contorller 修饰的类对应的对象也是一个Bean,是一个注解,
         */
        @AliasFor(annotation = Component.class)
        String value() default "";
    
    }
    

           @Controller的作用很简单,就是表示添加了该注解的类是负责处理由DispatcherServlet 分发的http请求的。

    11.2 @RestController

           @RestController是一个组合注解,@Controller+@ResponseBody。关于@ResponseBody的解释,我们会在下文讲到。

    11.3 @RequestMapping

    @Target({ElementType.METHOD, ElementType.TYPE}) // 可以作用于类,接口,方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Mapping
    public @interface RequestMapping {
    
        /**
         * 为该映射起一个名字
         */
        String name() default "";
    
        /**
         * 指定请求的实际地址
         */
        @AliasFor("path")
        String[] value() default {};
        @AliasFor("value")
        String[] path() default {};
    
        /**
         * 指定请求的method类型, GET、POST、PUT、DELETE等
         */
        RequestMethod[] method() default {};
    
        /**
         * 指定request中必须包含某些参数值,才让该方法处理
         * 1. param1: 表示请求必须包含名为param1的请求参数
         * 2. !param1: 表示请求不能包含名为param1的请求参数
         * 3. param1!=value1: 表示请求包含名为param1的请求参数,但其值不能为 value1
         * 4. {"param1=value1", "param2"}: 请求必须包含名为 param1和param2的两个请求参数,且 param1参数的值必须为 value1
         */
        String[] params() default {};
    
        /**
         * 指定request中必须包含某些指定的header值,才能让该方法处理请求。
         * 比如, @RequestMapping(value = "/something", headers = "content-type=text/*")
         * 将会匹配所有请求里面包含 Content-Type of "text/html", "text/plain", etc.
         */
        String[] headers() default {};
    
        /**
         * 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html
         * Examples:
         * consumes = "text/plain"
         * consumes = {"text/plain", "application/*"}
         */
        String[] consumes() default {};
    
        /**
         * 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
         * Examples:
         * <pre class="code">
         * produces = "text/plain"
         * produces = {"text/plain", "application/*"}
         * produces = MediaType.APPLICATION_JSON_UTF8_VALUE
         * </pre>
         */
        String[] produces() default {};
    
    }
    

           @RequestMapping是一个用来处理请求地址映射的注解。该注解可用于类或方法上,用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。@RequestMapping最终的目的就是把http对应的请求映射到对应的方法上。

    11.3 @PathVariable

    @Target(ElementType.PARAMETER) // 该注解用于添加在参数上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface PathVariable {
    
        /**
         * Alias for {@link #name}.
         */
        @AliasFor("name")
        String value() default "";
    
        /**
         * 要绑定的路径变量的名称
         */
        @AliasFor("value")
        String name() default "";
    
        /**
         * 该属性是否是必须的,如果设置成必须的,但是路径里面没有传递该变量过来就抛出异常
         */
        boolean required() default true;
    
    }
    

           @PathVariable注解用于从url中获取数据。

    11.4 @RequestParam

    @Target(ElementType.PARAMETER) // 该注解只能加载参数上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface RequestParam {
    
        /**
         * 请求参数名
         */
        @AliasFor("name")
        String value() default "";
        @AliasFor("value")
        String name() default "";
    
        /**
         * 是否为必须参数
         */
        boolean required() default true;
    
        /**
         * 默认值,没有匹配到参数情况下的默认值
         */
        String defaultValue() default ValueConstants.DEFAULT_NONE;
    
    }
    

           @RequestParam用于将请求参数绑定至方法参数。

    11.5 @RequestBody

    @Target(ElementType.PARAMETER) // 该注解用于添加在参数上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface RequestBody {
    
        /**
         * 该参数是否是必须的(是否非空)
         */
        boolean required() default true;
    
    }
    
    

           该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上。简单来说就是把Request请求对应的body数据映射成参数里面的对象。

    11.6 @ResponseBody

    @Target({ElementType.TYPE, ElementType.METHOD}) // 该注解用于添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ResponseBody {
    
    }
    

           该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。

    11.7 @ModelAttribute

    @Target({ElementType.PARAMETER, ElementType.METHOD}) // 该注解用于添加在类或者方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ModelAttribute {
    
        /**
         * Alias for {@link #name}.
         */
        @AliasFor("name")
        String value() default "";
    
        /**
         * 要绑定的model属性的名称
         */
        @AliasFor("value")
        String name() default "";
    
        /**
         *
         * 允许直接在ModelAttribute方法参数或从ModelAttribute方法返回的属性上声明数据绑定,这两种方法都会阻止该属性的数据绑定。
         */
        boolean binding() default true;
    
    }
    

           @ModelAttribute注解的主要作用是绑定request或是form参数到模型(Model)对象。可以使用保存在request或session中的对象来组装模型对象。注意,被@ModelAttribute注解的方法会在controller方法(@RequestMapping注解的)之前执行。因为模型对象要先于controller方法之前创建。

    11.7.1 @ModelAttribute添加在方法上

           @ModelAttribute注解在方法上说明方法的作用是用于添加一个或多个属性到Model上。被@ModelAttribute注释的方法会在此Controller每个方法执行前被执行。因此对于一个Controller映射多个URL的用法来说,要谨慎使用。

    11.7.1.1 @ModelAttribute添加在没有返回值的方法上

           @ModelAttribute添加的方法没有返回值,一般这个时候我们需要自己去往Model里面添加数据了,要不然没啥意义。Model 就相当于每次请求的一个背包,我们可以往背包里面放东西。

        /**
         * Model: 就相当于每次请求的一个背包,我们可以往背包里面放东西
         */
        @ModelAttribute
        public void postVoidModelAttribute(@RequestParam String abc, Model model) {
            // 往model里面添加一个属性
            model.addAttribute("userId0", abc);
        }
    

    11.7.1.2 @ModelAttribute添加在有返回值的方法上

           @ModelAttribute添加在有返回值的方法上,会自动将该返回值放到Model里面去。

    其实咱们这里的两个例子是等效的,都是把@RequestParam对应的值放到Model里面去了。

        /**
         * Model: 就相当于每次请求的一个背包,我们可以往背包里面放东西
         * @ModelAttribute 添加在有返回值的放的方法上,会把返回值放到Model里面去
         */
        @ModelAttribute(value = "userId1")
        public String postReturnModelAttribute(@RequestParam String abc) {
            return abc;
        }
    

    11.7.2 @ModelAttribute添加在参数上

           @ModelAttribute添加在参数上的时候用于从Model里面获取数据。上面我们已经通过把@ModelAttribute添加在方法上往Model里面添加了数据了,是时候取出来了。

        /**
         * Model: 就相当于每次请求的一个背包,我们可以往背包里面放东西
         * 会在其他添加了@RequestMapping的方法之前执行
         */
        @ModelAttribute
        public void postVoidModelAttribute(@RequestParam String abc, Model model) {
            // 往model里面添加一个属性
            model.addAttribute("userId0", abc);
        }
    
        /**
         * Model: 就相当于每次请求的一个背包,我们可以往背包里面放东西
         * @ModelAttribute 添加在有返回值的放的方法上,会把返回值放到Model里面去
         * 会在其他添加了@RequestMapping的方法之前执行
         */
        @ModelAttribute(value = "userId1")
        public String postReturnModelAttribute(@RequestParam String abc) {
            return abc;
        }
    
        /**
         * 上面我们已经通过把@ModelAttribute添加在方法上往Model里面去了,这个时候我们可以通过把@ModelAttribute添加在参数上获取Model里面的值
         */
        @RequestMapping(value = "/text0")
        public String test0(@RequestParam String abc, @ModelAttribute("userId0") String userId) {
            System.out.println(userId);
            return "helloWorld";
        }
    
        /**
         * 其实我们也可以直接拿到Model
         */
        @RequestMapping(value = "/text1")
        public String helloWorld(@RequestParam String abc, Model model) {
            Map<String, Object> mapList = model.asMap();
            return "helloWorld";
        }
    

    11.8 @InitBinder

    @Target({ElementType.METHOD}) // 该注解只能添加在方法上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface InitBinder {
    
        /**
         * value,作用是限制对哪些 @RequestMapping 方法起作用,
         * 具体筛选条件就是通过@RequestMapping方法入参来筛选,
         * 默认不写就代表对所有@RequestMapping的方法起作用。
         */
        String[] value() default {};
    
    }
    

           @InitBinder:用于给Binder做初始化,被@InitBinder注解的方法可以对WebDataBinder初始化。WebDataBinder是用于表单到方法的数据绑定的。只在添加了@InitBinder注解方法所在的控制器(Controller)里面有效。@InitBinder对应的方法在Controller的请求执行映射的方法之前被执行。同时添加了@InitBinder注解的方法返回值必须为null。

           我们用一个具体的实例来说明@InitBinder的用法,可能有这么个场景,关于时间部分我们调用接口的时候传递的是 “2019-09-05” 的格式,但是我们后天需要Date的格式。这个时候@InitBinder就派上大用场了呀,我们可以通过@InitBinder配合WebDataBinder的使用帮我们把 “2019-09-05” 转换成Date。

    @RestController
    @RequestMapping(path = "/initBinder")
    public class InitBinderController {
    
        /**
         * 对当前控制器的所有请求都有效
         * 前台传递过来的String类型时间,通过下面的初始化绑定,转换成Date类型
         */
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            // 我们前台传过来的time字段对应的值可能是“2019-05-06”这样的,我们可以在这里把他们转换成Date类型的
            binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
        }
    
    
        @RequestMapping(value = "/test", method = RequestMethod.POST)
        public String helloWorld(@RequestBody InitBinderTestVo vo) {
            System.out.println(vo.getTime());
            return "success";
        }
    
    }
    

    11.9 @ExceptionHandler

    @Target(ElementType.METHOD) // 标记该注解是添加在方法上的
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ExceptionHandler {
    
        /**
         * 当产生了哪些异常,就执行当前注解添加的方法
         */
        Class<? extends Throwable>[] value() default {};
    
    }
    

           @ExceptionHandler用于全局处理控制器里的异常

    11.10 @ControllerAdvice、@RestControllerAdvice

    @Target(ElementType.TYPE) // 该注解是添加在类上的
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface ControllerAdvice {
    
        /**
         * 指定包下的控制器(Controller)
         */
        @AliasFor("basePackages")
        String[] value() default {};
        @AliasFor("value")
        String[] basePackages() default {};
    
        /**
         * 指定类所在的包和子包里面的控制器(Controller)
         */
        Class<?>[] basePackageClasses() default {};
    
        /**
         * 直接给定控制器对应的class
         */
        Class<?>[] assignableTypes() default {};
    
        /**
         * 添加了指定注解的控制器(Controller)
         */
        Class<? extends Annotation>[] annotations() default {};
    
    }
    

           @ControllerAdvice(@RestControllerAdvice),Controller增强器。可以将对于控制器的全局配置(@ExceptionHandler、@InitBinder、@ModelAttribute)放在同一个位置(放到添加了@ControllerAdvice类中去实现)。所有有@ControllerAdvice出现的地方的类的方法里面肯定被@ExceptionHandler、@InitBinder、@ModelAttribute当中的一个修饰。


           关于Spring Boot注解的简单介绍就这么写,希望能帮助到大家.

    相关文章

      网友评论

        本文标题:Spring Boot 注解收集

        本文链接:https://www.haomeiwen.com/subject/pjeuyctx.html