通过自定义注解+切面给执行方法加锁

通过自定义注解+切面给执行方法加锁

上代码
一、自定义注解类=================================
@Target({ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface XXXLock {
String lockKey();
String keyExtendField() default StringUtils.EMPTY;
String lockDesc() default “aaaa”;
long expireTime() default 1111111L;
}

二、类中加了注解的方法========================
@Service
public class XXXServiceImpl{
private String bbbbype;
@XXXLock (lockKey = xxxKey, keyExtendField = “bbbbype”)
public void acquireMorningStaticContractInfo() {}
}

三、切面类===============================
@Component
@Aspect
public class XXXLockAspect {
@Pointcut(“@annotation(annotation.XXXLock )”)
public void pointCut() {}
@Around(“pointCut()”)
public Object doAround(ProceedingJoinPoint joinPoint) throws Exception {
Object result = null;
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
//获取目标对象
Object target = joinPoint.getTarget();
//目标方法
Method method = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
//方法注解
XXXLock annotation = method.getAnnotation(XXXLock.class);
//注解定义的key
String key = annotation.lockKey();
if (!StringUtils.EMPTY.equals(annotation.keyExtendField())) {
//通过反射获取扩展字段
Field bbbbypeF = target.getClass().getDeclaredField(annotation.keyExtendField());
ctyTypeF.setAccessible(true);
//获取字段值
String keyExtend = (String) bbbbypeF.get(target);
//拼接生成key
key = key + xxxx + keyExtend;
}
XXXLockDO xxxLockDO = DomainFactory.create(XXXLockDO.class);
//是否获取到锁
boolean isAcquired = xxxLockDO .setLockKey(key)
.setLockDesc(annotation.lockDesc())
.setLockExpireTime(annotation.expireTime())
.acquireLock();
if (isAcquired) {
try {
//获取到锁,执行方法,否则不执行
result = joinPoint.proceed();
} catch (Throwable throwable) {
throw new Exception(xxxx);
}
} else {
}
return result;
}
}

四、获取锁的类的方法=========================
public class XXXLockDO {
@Override
public boolean acquireLock() {
Date now = new Date();
this.setCreateTime(now);
this.setLastUpdateTime(now);
try {
//通过key去库中查询是否存在锁
XXXLockPO lockInstance = repository.getKey(this.lockKey);
if (Objects.nonNull(lockInstance)) {//如果当前key存在锁
if (lockInstance.getCreateTime().getTime() + Optional.ofNullable(lockInstance.getLockExpireTime()).orElse(0L) < now.getTime()) {//判断锁是否过期
//如果锁过期就释放锁,删除表中记录
repository.releaseLock(lockInstance.getLockId());
} else {
//没有获取到锁
return false;
}
}
//表中不存在记录就入库加锁,返回true,获取到锁
repository.insert(convertor.convert(this));
} catch (Exception e) {
return false;
}
return true;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,你的问题是关于如何在Spring Boot应用中实现多数据源动态切换,使用的技术包括Spring Boot、MyBatis、MySQL、Oracle、Druid数据源连接池、自定义注解切面,并且配置文件使用application.yml格式。 首先,需要在pom.xml文件中添加相应的依赖: ```xml <!--Spring Boot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--MyBatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> <!--MySQL--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <!--Oracle--> <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc8</artifactId> <version>19.3.0.0</version> </dependency> <!--Druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency> ``` 接下来,需要在application.yml文件中配置数据源和MyBatis相关的属性,例如: ```yaml spring: datasource: druid: # 数据源1 db1: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: root # 数据源2 db2: driver-class-name: oracle.jdbc.OracleDriver url: jdbc:oracle:thin:@localhost:1521:ORCL username: scott password: tiger # 默认数据源 url: jdbc:mysql://localhost:3306/db1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: root mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.demo.entity ``` 然后,需要定义一个自定义注解,用于标识哪些方法需要使用哪个数据源: ```java @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { String value() default "db1"; } ``` 在数据源切换的时候,我们需要获取注解上指定的数据源名称,因此需要定义一个切面: ```java @Aspect @Component public class DataSourceAspect { @Around("@annotation(ds)") public Object around(ProceedingJoinPoint point, DataSource ds) throws Throwable { String dataSourceName = ds.value(); DynamicDataSource.setDataSource(dataSourceName); try { return point.proceed(); } finally { DynamicDataSource.clearDataSource(); } } } ``` 最后,需要定义一个动态数据源,用于实现数据源的切换: ```java public class DynamicDataSource extends AbstractRoutingDataSource { private static final ThreadLocal<String> dataSourceHolder = new ThreadLocal<>(); @Override protected Object determineCurrentLookupKey() { return dataSourceHolder.get(); } public static void setDataSource(String dataSourceName) { dataSourceHolder.set(dataSourceName); } public static void clearDataSource() { dataSourceHolder.remove(); } } ``` 至此,多数据源动态切换的配置就完成了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值