SpringBoot中Server层以及Mapper层常用注解

1,557 阅读22分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

👨‍🎓作者:Java学术趴

🏦仓库:GithubGitee

✏️博客:CSDN掘金InfoQ云+社区

💌公众号:Java学术趴

🚫特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系小编授权。

🙏版权声明:文章里的部分文字或者图片来自于互联网以及百度百科,如有侵权请尽快联系小编。微信搜索公众号Java学术趴联系小编。

☠️每日毒鸡汤:堕落的一天

👋大家好!我是你们的老朋友Java学术趴。最近看了一下SpringBoot2的课程,发现好多的注解并不是很了解,只是简单的会用,但是真是发生的作用却不知道,最近花了一些时间把这些注解进行了一下整理,针对不同的层级进行了细致的划分,最近几天会依次给大家更新关于注解的内容,对大家有帮助的话点赞支持一下哦!

4. Service层注解

@Service注解一般写在业务层的接口实现类上,而不是接口上。

4.1 @Service

@Service : @Service注解用于类上,标记当前类是一个service类,加上该注解会将当前类自动注入到spring容中。


@Service
public class CourseDAOImpl extends HibernateDaoSupport implements CourseDAO{
        ...    
}

@Service("courseDAOImpl") :这个表示给类命名一个别名,方便注入到其他类中。不加这个参数值的话,默认别名就是当前类名,但是首字母小写。

在实际开发中,我们一般都直接使用 @Sevice

4.2 @Scope

@Scope :Spring IOC 容器中的一个作用域,在 Spring IOC容器中,他用来配置Bean实例的作用域对象。

@Scope的几种作用域:

  • singleton 单实例的(单例)(默认)   ----全局有且仅有一个实例。
  • prototype 多实例的(多例)   ---- 每次获取Bean的时候会有一个新的实例。
  • reqeust   同一次请求 ----request:每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效。
  • session   同一个会话级别 ---- session:每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效。

默认的作用域是:singleton(单实例)

5. Mapper层注解

5.1 @Reponsitory

@Reponsitory :@Reponsitory的作用与@Controller,@Service的作用都是把对象交给Spring管理。@Reponsitory是标注在Dao层接口上,作用是将接口的一个实现类交给Spring管理。

注意:

  • 使用这个注解的前提是必须在启动类上添加 @MapperScan("Mapper接口层路径") 注解。

这个 @Repository 完全可以省略不写,也完全可以实现自动注入,但是在IDEA中会存在一个红色的波浪线。原因如下:

  • Spring配置文件中配置了MapperScannerConfiguer这个Bean,它会扫描持久层接口创建实现类并交给Spring管理。
  • SpringBoot的启动类上标注了@MapperScanner,它的作用和上面的MapperScannerConfiguer作用一样。

5.2 @Mapper

@Mapper : 这个注解一般使用在Dao层接口上,相当于一个mapper.xml文件,它的作用就是将接口生成一个动态代理类。加入了@Mapper注解,目的就是为了不再写mapper映射文件。这个注解就是用来映射mapper.xml文件的。

@Mapper使用的原理:

  • Mybatis 会有一个拦截器,会自动的把 @Mapper 注解的接口生成动态代理类。前提是,映射器(Mapper.xml)必须满足动态代理的条件:

    1. namespace声明的命名空间必须和Dao层接口的全限定类型一致。否者Mapper.xml这个映射器映射不到Dao层的接口类。
    2. Mapper.xml文件中sql语句的id名必须和接口的方法名一致。否则该sql语句对应不上指定的接口。

注意:

  • 在Dao层不要存在相同名字的接口,也就是在Dao不要写重载。因为mapper文件是通过id与接口进行对应的,如果写了两个同名的接口,就会导致mapper文件映射出错。

5.2.1 @Mapper注解和@MapperScan注解的区别

  • @Mapper注解写在每个Dao接口层的接口类上,@MapperScan注解写在SpringBoot的启动类上。

  • 当我们的一个项目中存在多个Dao层接口的时候,此时我们需要对每个接口类都写上@Mapper注解,非常的麻烦,此时可以使用@MapperScan注解来解决这个问题。让这个接口进行一次性的注入,不需要在写@Mapper注解

    
    @SpringBootApplication
    @MapperScan("cn.gyyx.mapper")
    // 这个注解可以扫描 cn.gyyx.mapper 这个包下面的所有接口类,可以把这个接口类全部的进行动态代理。
    public class WardenApplication {
        public static void main(String[] args) {
            SpringApplication.run(WardenApplication.class,args);
        }
    }
    
  • @Mapper注解相当于是@Reponsitory注解和@MapperScan注解的和,会自动的进行配置加载。

  • @MapperScan注解多个包,@Mapper只能把当前接口类进行动态代理。

在实际开发中,如何使用@Mapper、@MapperSacn、@Reponsitory注解???

  • 在SpringBoot的启动类上给定@MapperSacn注解。此时Dao层可以省略@Mapper注解,当让@Reponsitory注解可写可不写,最好还是写上。
  • 当使用@Mapper注解的时候,可以省略@MapperSacn以及@Reponsitory。

建议:

  • 以后在使用的时候,在启动类上给定@MapperScan("Dao层接口所在的包路径")。在Dao层上不写@Mapper注解,写上@Reponsitory即可。

5.3 @Select、@Insert、@Delete、@Update

5.3.1 基本用法

@Select :该注解的目的是为了取代mapper.xml中的select标签,只作用于方法上面。此时就不要在写mapper.xml文件了。

@Select注解的源码


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select
{
    String[] value();
}

从上述可以看到两点信息:

  • @Select注解只能修饰方法。
  • @Select注解的值是字符数组。

所以,@Select注解的用法是这样的:


@Select({ "select * from xxx", "select * from yyy" })
Person selectPersonById(Integer id);

虽然@Select注解的值是字符数组,但是真正生效的应该是最后那条SQL语句。这一点请大家要留意一下。

5.3.2 @Select注解动态SQL拼写(重点)

普通的字符串值,只能实现变量的替换功能,实现简单的SQL语句,如下所示,


@Select("select * from t_person where id = #{id}")
Person selectPersonById(Integer id);

如果要想实现复杂的逻辑判断,则需要使用标签 ,如下所示:


@Select("<script> select * from t_person where id = #{id} 
<when test='address !=null'> and address = #{address} 
</when> </script>")
Person selectPersonById(Integer id);

其实,标签 注解专用的,其他的注解,例如@Insert、@Update、@Delete等等,都可以使用的。

5.4 @Param

@Param : 动态代理接口向映射文件中传递参数的时候,会使用@Param注解,并且如果动态代理接口使用了@Param这个注解,那么映射文件中的标签中可以不用写parameterType属性,可以直接接收@Param中传递来的参数值。

先来看一下动态代理接口中是怎样写的,如下图:

再来看一下与动态代理接口对应的映射文件中是怎样接收参数的,如下图:

5.4.1 @Param注解基本类型的参数

mapper中的方法:


public User selectUser(@Param("userName") String name,@Param("password") String pwd);

映射到xml中的标签 <select id="selectUser" resultMap="User">     select * from user where user_name = #{userName} and user_password=#{password}   </select> 其中where user_name = #{userName} and user_password = #{password}中的userName和password都是从注解@Param()里面取出来的,取出来的值就是方法中形式参数 String name 和 String pwd的值。 重点:当只存在一个参数的时候,此时可以省略这个 @@Param注解,但是两个参数必须使用这个注解。 5.4.2 @Param注解JavaBean对象 SQL语句通过@Param注解中的别名把对象中的属性取出来然后复制 mapper中的方法: public List<User> getAllUser(@Param("user") User u); 映射到xml中的标签


<select id="getAllUser" parameterType="com.vo.User" resultMap="userMapper">  
        select   
        from user t where 1=1  
             and   t.user_name = #{user.userName}  
              and   t.user_age = #{user.userAge}  
    </select>  

注意点:

  • 当使用了@Param注解来声明参数的时候,SQL语句取值使用#{},${}取值都可以。
  • 当不使用@Param注解声明参数的时候,必须使用的是#{}来取参数。使用${}方式取值会报错。
  • 不使用@Param注解时,参数只能有一个,可以是一个基本的数据也可以是一个JavaBean。如果是JavaBean最好还是声明一个@Param注解。

6. 其他注解

6.1 @Configuration

@Configuration :用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

我们相当于把xml配置文件转换成了一个配置类。这个配置类就相当于xml配置文件。

注意:

  • @Configuration不可以是final类型;
  • @Configuration不可以是匿名类;
  • 嵌套的configuration必须是静态类。

@Configuration配置spring并启动spring容器

以前我们需要使用 xml 文件来进行spring的配置:

@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans>,作用为:配置spring容器(应用上下文)

@Bean注解就是声明其中的标签

@Configuation等价于

@Bean等价于

举例说明:将指定的组件添加到SpringBoot的IOC容器中。

  1. 主程序类

  1. 实体类

  1. 在spring中,我们如果想把这两个类交给Spring容器进行管理,那么必须写xml配置文件。

    • 需要在resources目录下创建一个xml配置文件
    • 创建bean标签

使用SpringBoot解决这个xml配置文件

现在的Spring Boot已经不需要向以前一样了,有一个注解@Configuration(翻译:配置)可以供使用

  • 创建一个类。
  • 在这个类的上面加上@Configuration,告诉Spring Boot这是一个配置类。
  • 此时这个配置类就相当于xml这个配置文件。其中的@Configuration就相当于xml配置文件中的标签

这个时候在类里边不能写bean标签了需要使用@bean注解,想要构建出user和pet对象需要自己将它创造出来。 @bean:给容器中添加组件,以方法名作为组件的id。返回类型为组件类型,返回的值,就是组件在容器中的实例对象。

注意:@Bean这个注解需要声明在方法名上面,使用@Configuration、@Bean就可以完全代替xml配置文件

这个配置文件会在SpringBoot启动的时候进行注册加载,就会创建出User以及Pet实例对象。

正常的实例名称就是方法的名称,当然可以使用修改这个实例对象的名字。

重点:给容器中注册的组件默认是单实例的,就是说无论我们从容器中获取多少次,这些实例对象都是同一个实例对象。当然被 @Configuration 注解的配置类也是一个组件。

同时,在Spring Boot 5.2之后的@Configuration注解多了一个属性proxyBeanMethods,默认为true(翻译:代理bean的方法)

6.2 @Bean

@Bean:这个注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中;

6.2.1 Bean是什么??

  • Java面向对象,对象有方法和属性,那么就需要对象实例来调用方法和属性(即实例化);
  • 凡是有方法或属性的类都需要实例化,这样才能具象化去使用这些方法和属性;
  • 规律:凡是子类及带有方法或属性的类都要加上注册Bean到Spring IoC的注解;
  • 把Bean理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了

6.2.2 注解分为两类

  1. 一类是使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装; 比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;
  2. 一类是注册Bean,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。

6.2.3 @Bean是什么??

  1. @Bean:Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。 产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中;
  2. SpringIOC 容器管理一个或者多个bean,这些bean都需要在@Configuration注解下进行创建,在一个方法上使用@Bean注解就表明这个方法需要交给Spring进行管理;
  3. @Bean是一个方法级别上的注解,主要用在 @Configuration注解的类里,也可以用在 @Component注解的类里。添加的bean的id为方法名,当然也可以使用 @Bean(value)中的value属性改变其中的id值。
  4. 使用Bean时,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装; 比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;
  5. 注册Bean时,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装;
  6. @Configuration与@Bean结合使用:@Configuration可理解为用spring的时候xml配置文件中的标签,@Bean可理解为用spring的时候xml配置文件里面的标签;

@Configuration
public class AppConfig {
​
    // 使用@Bean 注解表明myBean需要交给Spring进行管理
    // 未指定bean 的名称,默认采用的是 "方法名" + "首字母小写"的配置方式
    @Bean
    public MyBean myBean(){
        return new MyBean();
    }
}
​
public class MyBean {
​
    public MyBean(){
        System.out.println("MyBean Initializing");
    }
}

6.2.4 @Bean的属性

  • value: bean别名和name是相互依赖关联的,value,name如果都使用的话值必须要一致;
  • name:bean名称,如果不写会默认为注解的方法名称;
  • autowire: 自定装配默认是不开启的,建议尽量不要开启,因为自动装配不能装配基本数据类型、字符串、数组等,这是自动装配设计的局限性,并且自动装配不如依赖注入精确;
  • initMethod: bean的初始化之前的执行方法,该参数一般不怎么用,因为完全可以在代码中实现;
  • destroyMethod:默认使用javaConfig配置的bean,如果存在close或者shutdown方法,则在bean销毁时会自动执行该方法,如果你不想执行该方法,则添加@Bean(destroyMethod="")来防止出发销毁方法;

如果发现销毁方法没有执行,原因是bean销魂之前程序已经结束了,可以手动close下如下:


AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainConfig.class);
        User bean2 = applicationContext2.getBean(User.class);
        System.out.println(bean2);
        //手动执行close方法
        applicationContext2.close();

6.3 @Component

6.3.1 @Component注解

@component把普通pojo实例化到spring容器中,相当于xml配置文件中的 。泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。把当前类对象存入到Spring容器中。

  • 在没有这个注解之前,我们需要使用xml配置文件来把这个类注册到IOC容器中,代码如下:

<context:component-scan base-package=”com.mmnc”> 
# base-package表示为需要扫描的所有子包。
  • 此时我们完全可以使用 @Component 注解来完成以上的这个操作,只需要在配置类上加上@Component注解即可。在Spring启动的时候他会自动扫描这个注解将这个配置类交给Spring的IOC容器进行管理。

这个注解和@controller 、@service、@repository注解一样,都是把声明的类交给Spring进行管理。

6.3.2 @Component注解的属性

  • @Component注解属性主要指的是value属性。 value属性用于指定bean的id。当我们不写时,它的默认值是当前类名首字母改小写。当然一般情况下是不写的。

6.3.3@Component 和 @Bean 的区别是什么?

  • @Component 注解作用于类,而@Bean注解作用于方法。
  • @Component 注解是通过类路径扫描来自动装配到IOC容器中的,而@Bean注解是将方法返回值作为bean装载到IOC容器中。
  • @Bean注解比@Component注解的自定义性更强,而且很多地方我们只能通过@Bean注解来注册bean。比如当我们引用第三方库中的类需要装配到Spring容器时,则只能通过@Bean来实现而不能通过@Component注解来实现(其实很好理解:你总不能在第三方类上加@Component注解吧)。

6.4 @Scheduled(cron = "0/30 * * * * ?")

6.4.1 基础概念

@Scheduled : 这个注解是spring boot提供的用于定时任务控制的注解,主要用于控制任务在某个指定时间执行,或者每隔一段时间执行.使用这个注解的前提是需要在SpirngBoot的启动类上加入 @EnableScheduling注解。

@Scheduled使用在定时任务的方法上,@EnableScheduling使用在SpringBoot启动类上。

6.4.2 @Scheduled属性

配置@Scheduled中执行的时间有三种方式:cron表达式、fixedRate、fixedDelay。

其中还存在一个针对首次执行定时任务进行设置的属性:initialDelay

6.4.2.1 corn属性

corn属性: 使用corn表达式可以指定定时任务执行的指定时间。

cron是@Scheduled的一个参数,是一个字符串,以5个空格隔开,只容许6个域(注意不是7个,7个直接会报错),分别表示秒、分、时、日、月、周。

cron通配符

cron使用的普通示例


@Scheduled(cron = "0 * * * 1 SAT") //每一年的1月的全部周六的全部0秒时间执行
@Scheduled(cron = "0 0 0 1 Jan ?") //每一年的1月的1日的0时0分0秒执行

cron支持占位符的使用

如果在SpringBoot的配置文件中存在常量 : cron = 2 2 2 2 2 ?

可以使用占位符的方式获取到这个常量,直接使用即可,相当于@Value注解。


@Scheduled(cron = "${cron}") // 表示每一年的二月二号的两时两分两秒执行

6.4.2.2 fixedRate属性

  • fixedRate表示自上一次执行时间以后多长时间执行,以ms为单位。参数值是一个int类型的数据。

@Scheduled(fixedRate = 1000 * 5) // 自上次执行以后5秒再执行

6.4.2.3 fixedRateString属性

  • 这个属性和fixedRate属性是一样的。只是这个属性的值是字符串类型,而不是int类型。并且这个属性支持占位符。

@Scheduled(fixedRateString = "1000") // 自上次执行1秒再执行

若在配置文件中有相应的属性,能够用占位符获取属性,如在application.yml中有 interval=2000


@Scheduled(fixedRateStirng="${interval}") // 自上次执行2秒后在执行

6.4.2.4 fixedRate属性

fixedDelay与fixedRate有点相似,不过fixedRate是上一次开始以后计时,fixedDelay是上一次结束以后计时,也就是说,fixedDelay表示上一次执行完毕以后多长时间执行,单位也是ms,他是int类型


@Scheduled(fixedDelay = 1000 * 3600 * 12) //上一次执行完毕后半天后再次执行

6.4.2.4 fixedDelayString属性

与fixedDelay相似,属性值是字符串类型的数据,也是支持占位符。


@Scheduled(fixedDelayString = "${fixedDelay}")

6.4.2.4 initialDelay属性

initialDelay表示首次延迟多长时间后执行,单位ms,以后按照cron/fixedRate/fixedRateString/fixedDelay/fixedDelayString指定的规则执行,须要指定其中一个规则。属性值是int类型。

注意:这个属性只针对第一次执行这个定时任务生效。


@Scheduled(initialDelay=1000,fixedRate=1000) //首次运行延迟1s

6.4.2.4 initialDelayString属性

与initialDelay相似,不过属性值是字符串,支持占位符。


@Scheduled(initialDelayString = "${initialDelay}",cron = "0 0 0 14 4 ?") 
//按照配置文件initialDelay指定的时间首次延迟,并于每一年4月14日0时0分0秒执行

重点:initialDelay、initialDelayString都不能和cron一起使用

6.6 @EnableCaching

@EnableCaching : 这个注解是spring framework中的注解驱动的缓存管理功能。自spring版本3.1起加入了该注解。如果你使用了这个注解,那么你就不需要在XML文件中配置cache manager了。

当你在配置类@Configuration上使用@EnableCaching注解时,会触发一个post processor,这会扫描每一个spring bean,查看是否已经存在注解对应的缓存。如果找到了,就会自动创建一个代理拦截方法调用,使用缓存的bean执行处理。


@EnableCaching //开启缓存@Configuration  //配置类
​
public class RedisConfig extends CachingConfigurerSupport {
    ...
}

6.5 @Cacheable(cacheNames = "detectionDetail",key = "#ip")

6.5.1 基础用法

@Cacheable :该标注在方法上,表示该方法的结果需要被缓存起来,缓存的键由 keyGenerator 的 策略决定,缓存的值的形式则由serialize 序列化策略决定 ( 序列化还是 json 格式 ) ;标注上该注解之 后,在缓存时效内再次调用该方法时将不会调用方法本身而是直接从缓存获取结果。

@Cacheable作用:把方法的返回值添加到Ehcache缓存中。以后查询相同的数据,直接从缓存中取,不需要调用方法


@Override
@Cacheable(cacheNames = "CategoryLisxxxtByParentId", key = "#parxxxentId")
public List<Category> listByPaxxrentId(Long parentId) {
    return categoryMapper.listBxxyParentId(parentId,0l);
}
// 此时会把返回的List集合数据存储到缓存中,之后在查询相同数据的时候,直接从缓存中获取而不执行这个方法。

重点:

  • 其中value表示该方法返回的参数的缓存存在那个Cache里(即为缓存块的名字)
  • 缓存结果以一个键值对存放在缓存中,注解中key即为键值对的key;value即为方法返回的结果
  • key用双引号,里面#加上方法的参数:获取方法的参数, ''表示在参数之间添加分隔符
  • 缓存中存储数据的结构是:key--value的形式

6.5.2 属性:

  • cacheNames/value :用来指定缓存组件的名字,将方法的返回结果放在哪个缓存中,可以是数组的方式,支持指定多个缓存。

// 指定单个缓存的名字
@Cacheable(cacheNames = "streamUrl", key = "#eventId", unless = "#result == null")
// 指定多个缓存的名字,以数组的形式指定
@Cacheable(cacheNames = {"streamUrl", "test"}, key = "#eventId", unless = "#result == null")
​
  • key :缓存数据时使用的 key。默认使用的是方法参数的值。可以使用 spEL 表达式去编写。

// 这里必须使用spEL表达式指定
@Cacheable(cacheNames = "detectionDetail",key = "#ip")
public List<AssetsDetectionScriptVo> detectionDetail(String ip) {
    ...
}
  • keyGenerator: key 的生成器,可以自己指定 key 的生成器,通过这个生成器来生成 key。

// 使用自定义的key生成器自动生成key值
@Cacheable(value = "ip", keyGenerator = "cacheKeyGenerator")
public IPResponse query(String ip) {
  return ipAPI.query(ip);
}

@Slf4j
@Component
// 以下是自定义key生成器的规则
public class CacheKeyGenerator implements KeyGenerator {
    @Override
    public Object generate(Object target, Method method, Object... params) {
       //...
        return key.toString();
    }
}
​

这样放入缓存中的 key 的生成规则就按照你自定义的 keyGenerator 来生成。

注意:

key 和 keyGenerator属性在使用的时候一般二选一。

  • condition:符合条件的情况下才缓存。方法返回的数据要不要缓存,可以做一个动态判断。

// 表示 id 大于 1 才进行缓存,把返回的结果存储到 stramUrl 的缓存中。小于1的不会进行缓存。
@Cacheable(cacheNames = "streamUrl", condition = "#id > 1")
  • unless:否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过 #result 获取方法结果)

// #result可以接收到这个方法的返回值,对这个返回值进行判断。当返回的数据为nnull的时候不做缓存。
@Cacheable(cacheNames = "streamUrl", key = "#eventId", unless = "#result == null")
  • sync :是否使用异步模式。默认是方法执行完,以同步的方式将方法返回的结果存在缓存中。

6.5.3 spEL 编写 key

前面说过,缓存的 key 支持使用 spEL 表达式去编写,下面总结一下使用 spEL 去编写 key 可以用的一些元数据:

6.7 @CacheEvict

6.7.1 基础用法

@CacheEvict : 该注解是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时,表示其中所有的方法的执行都会触发缓存的清除操作。当标记在一个方法上的时候,只有该方法会触发清除缓存操作,不会影响其他的方法。

6.7.2 属性

@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。

  • value表示清除操作是发生在哪些Cache上的(对应Cache的名称)。
  • key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key。
  • condition表示清除操作发生的条件。

下面我们介绍这个注解特有的两个属性:

  • allEntries属性 :allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,清除缓存中的所有元素,Spring Cache将忽略指定的key(也就是当指定allEntries属性为true的时候就不需要给定key属性,没有必要)

大多数情况下我们都是直接删除缓存中的全部元素,而不是使用key一个个的删除缓存中的数据。

  • beforeInvocation属性 : 清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

6.8 @PostConstruct 和 @PreDestroy

6.8.1 基础用法

  • javaEE5引入了@PostConstruct和@PreDestroy两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作。

6.8.2 使用场景

  • 在项目中主要是在Servlet初始化之前加载一些缓存数据以及测试定时任务等

6.8.3 使用该注解的特点

  • 只有一个非静态方法能使用此注解
  • 被注解的方法不得有任何参数
  • 被注解的方法返回值必须为void
  • 被注解方法不得抛出已检查异常
  • 此方法只会被执行一次

@PostConstruct
public void heartbeatAlarm() {
  ....
}

6.8.4 注意

使用此注解时会影响服务启动时间。服务启动时会扫描WEB-INF/classes的所有文件和WEB-INF/lib下的所有jar包。

6.8.5 @PostConstruct注解的用法

@PostConstruct是java5的时候引入的注解,指的是在项目启动的时候执行这个方法,也可以理解为在spring容器启动的时候执行,可作为一些数据的常规化加载,比如数据字典之类的。

数据字典:也就是在项目启动的时候直接返回给前端的数据,不需要前端发送请求获取。直接在启动项目的时候就会把这些数据返回给前端,然后前端进行显示。

被@PostConstruct修饰的方法会在服务器加载Servle的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行。

项目启动时的加载顺序:

服务器加载Servlet -> servlet 构造函数的加载 -> postConstruct ->init(init是在service 中的初始化方法. 创建service 时发生的事件.) ->Service->destory->predestory->服务器卸载serlvet

spring中Constructor(构造函数)、@Autowired、@PostConstruct的顺序:

Constructor >> @Autowired >> @PostConstruct