0
点赞
收藏
分享

微信扫一扫

利用Spring AOP + 注解实现通用开关

先实现一个自定义注解

@Target({ElementType.METHOD})  // 作用在方法上
@Retention(RetentionPolicy.RUNTIME)  // 运行时起作用
public @interface ServiceSwitch {

	/**
	 * 业务开关的key(不同key代表不同功效的开关)
	 */
	String switchKey();

	// 提示信息,默认值可在使用注解时自行定义。
	String message() default "该功能已被关闭,请联系管理员";
}

编写一个切面类,用于拦截需要进行开关操作的接口

@Aspect
@Component
@Slf4j
@AllArgsConstructor
public class ServiceSwitchAOP {

	private final StringRedisTemplate redisTemplate;

	/**
	 * 定义切点,使用了@ServiceSwitch注解的类或方法都拦截
	 */
	@Pointcut("@annotation(com.jy.demo.annotation.ServiceSwitch)")
	public void pointcut() {
	}

	@Around("pointcut()")
	public Object around(ProceedingJoinPoint point) {

		// 获取被代理的方法的参数
		Object[] args = point.getArgs();
		// 获取被代理的对象
		Object target = point.getTarget();
		// 获取通知签名
		MethodSignature signature = (MethodSignature) point.getSignature();

		try {

			// 获取被代理的方法
			Method method = target.getClass().getMethod(signature.getName(), signature.getParameterTypes());
			// 获取方法上的注解
			ServiceSwitch annotation = method.getAnnotation(ServiceSwitch.class);

			// 核心业务逻辑
			if (annotation != null) {

				String switchKey = annotation.switchKey();
				String message = annotation.message();
				// 从redis中获取启用状态
				String configVal = redisTemplate.opsForValue().get(switchKey);
        // 这里0代表已关闭
				if ("0".equals(configVal)) {
					// 开关关闭,则返回提示,返回类自行封装也可以使用SpringBoot中的ResponseEntity
					return new Result<>(HttpStatus.FORBIDDEN.value(), message);
				}
			}

			// 放行
			return point.proceed(args);

		} catch (Throwable e) {
      // 自定义的业务异常
			throw new BusinessException(e.getMessage(), e);
		}
	}
}

应用

	/**
	 * 测试
	 */
	@ServiceSwitch(switchKey = "test")
	public Result test() {
    // ...实现具体业务逻辑
		return new Result(HttpStatus.OK.value(), "测试");
	}

举报

相关推荐

0 条评论