spring、springboot常用注解详解

缓存注解

@Cacheable 注解在方法上,表示该方法的返回结果是可以缓存的。也就是说,该方法的返回结果会放在缓存中,以便于以后使用相同的参数调用该方法时,会返回缓存中的值,而不会实际执行该方法。

@Override
    @Cacheable({"menu", "menuById"})
    public Menu findById(String id) {
        Menu menu = this.getById(id);
        if (menu != null){
            System.out.println("menu.name = " + menu.getName());
        }
        return menu;
    }

---------
@GetMapping("/findById/{id}")
public Menu findById(@PathVariable("id")String id){
    Menu menu0 = menuService.findById("fe278df654adf23cf6687f64d1549c0a");
    Menu menu2 = menuService.findById("fb6106721f289ebf0969565fa8361c75");
    return menu0;
}

可以多个key,结果
在这里插入图片描述
1、一个缓存名对应一个被注解的方法,但是一个方法可能传入不同的参数,那么结果也就会不同,这应该如何区分呢?

其实用传入的参数在作为key值拼接起来即可

有三种生成方案
1、spring自动生成的id #id
2、由参数生成的key
3、对象的hashCode()

代码如下:


/**一般是用这种方法*/
@Override
    @Cacheable(value = {"menuById"}, key = "#id")
    public Menu findById(String id) {
        Menu menu = this.getById(id);
        if (menu != null){
            System.out.println("menu.name = " + menu.getName());
        }
        return menu;
    }

    @Override
    @Cacheable(value = {"menuById"}, key = "'id-' + #menu.id")
    public Menu findById(Menu menu) {
        return menu;
    }

    @Override
    @Cacheable(value = {"menuById"}, key = "'hash' + #menu.hashCode()")
    public Menu findByHash(Menu menu) {
        return menu;
    }

在这里插入图片描述
也可以跟进条件来缓存
condition

@Override
    @Cacheable(value = {"menuById"}, key = "#id", condition = "#conditionValue > 1")
    public Menu findById(String id, Integer conditionValue) {
        Menu menu = this.getById(id);
        if (menu != null){
            System.out.println("menu.name = " + menu.getName());
        }
        return menu;
    }
@GetMapping("/findById/{id}")
    public Menu findById(@PathVariable("id")String id){
        Menu menu0 = menuService.findById("fe278df654adf23cf6687f64d1549c0a", 0);
        Menu menu2 = menuService.findById("fb6106721f289ebf0969565fa8361c75", 2);
        return menu0;
    }

在这里插入图片描述
@CacheEvict

spring cache 也支持使用 @CacheEvict 来删除缓存

@Override
    @CacheEvict(value = "menuById", key = "#id")
    public Boolean deleteById(String id) {
        return this.removeById(id);
    }
@DeleteMapping("/deleteById/{id}")
    public Boolean deleteById(@PathVariable("id")String id){
        return menuService.deleteById(id);
    }

在这里插入图片描述
redis和mysql都成功删除

@CacheEvict有个属性beforeInvocation,默认是false,先执行方法(数据库),再操作缓存。
当值为true时,,先执行缓存,再操作方法(数据库)。

@Override
@CacheEvict(value = "menuById", key = "#id", beforeInvocation = true)
public Boolean deleteById(String id) {
    System.out.println("开始操作 db");
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Boolean result = this.removeById(id);
    System.out.println("db 操作结束");
    return result;
}

在这里插入图片描述
2、@ConditionalOnMissingBean,它是修饰bean的一个注解,主要实现的是,当你的bean被注册之后,如果而注册相同类型的bean,就不会成功,它会保证你的bean只有一个,即你的实例只有一个,当你注册多个相同的bean时,会出现异常,以此来告诉开发人员

3、注解@BeanFactoryPostProcessor

接口与 BeanPostProcessor接口类似,可以对bean的定义(配置元数据)进行处理;也就是spring ioc运行BeanFactoryPostProcessor在容器实例化任何其他的bean之前读取配置元数据,并有可能修改它;如果业务需要,可以配置多个BeanFactoryPostProcessor的实现类,通过"order"控制执行次序(要实现Ordered接口)。

4、@ConditionalOnBean // 当给定的在bean存在时,则实例化当前Bean
@ConditionalOnMissingBean // 当给定的在bean不存在时,则实例化当前Bean
@ConditionalOnClass // 当给定的类名在类路径上存在,则实例化当前Bean
@ConditionalOnMissingClass // 当给定的类名在类路径上不存在,则实例化当前Bean
@ConditionalOnProperty 控制配置类是否生效,可以将配置与代码进行分离,实现了更好的控制配置.
下面例子:

@Bean(name = "smsNotification")
@ConditionalOnProperty(prefix = "notification", name = "service", havingValue = "sms")
public NotificationSender notificationSender2() {
    return new SmsNotification();
}
借助于hadingValue属性,清楚地表明,仅当notification.service设置为sms时,才希望加载SmsNotification。

源码详解

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {


	//name的别名,和value不可同时使用
	String[] value() default {};

	/**配置项的前缀,例如完整的配置是config.person.enable=true
	* 那 prefix=“config.person”
	*/
	String prefix() default "";

	/**
	配置项的属性,例如完整的配置是config.person.enable=true
	在前面已经设置 prefix=“config.person”
	那么 name=“enable”;
	
	如果prefix没有设置,那么name可以是整个配置项,例如下面:
	name=“config.person.enable”,效果和上面的一样
	 */
	String[] name() default {};

	/**
	 * 会将配置文件中的值和havingValue的值对比,如果一样则加载Bean,例如:
	 * 
	 * config.person.enable=true,havingValue=“true”,加载Bean
	 * 
	 * config.person.enable=false,havingValue=“false”,加载Bean
	 * 
	 * config.person.enable=ok,havingValue=“ok”,加载Bean
	 * 
	 * config.person.enable=false,havingValue=“true”,不加载Bean
	 * 
	 * config.person.enable=ok,havingValue=“no”,不加载Bean
	 * 
	 * 当然havingValue也可以不设置,只要配置项的值不是false或“false”,都加载Bean,例如:
	 * 
	 * config.person.enable=ok,不设置havingValue,加载Bean
	 * 
	 * config.person.enable=false,不设置havingValue,不加载Bean
	 */
	String havingValue() default "";

	/**
	 * 如果在配置文件中没有该配置项,是否加载Bean
	 */
	boolean matchIfMissing() default false;

}

@ConfigurationProperties
使用@ConfigurationProperties和@Bean注解在配置类的Bean定义方法上。以数据源配置为例:

@Configuration
public class DataSourceConfig {

	@Primary
	@Bean(name = "primaryDataSource")
	@ConfigurationProperties(prefix="spring.datasource.primary")
	public DataSource primaryDataSource() {
		return DataSourceBuilder.create().build();
	}
}

这里便是将前缀为“spring.datasource.primary”的属性,赋值给DataSource对应的属性值。

@Configuration注解的配置类中通过@Bean注解在某个方法上将方法返回的对象定义为一个Bean,并使用配置文件中相应的属性初始化该Bean的属性。

码云地址:https://gitee.com/yuisuiWork/spring_project_demo/
欢迎交流,一起进步!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有点东西且很多

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值