使用@interface之前先了解注解
标准注解
@Override:表示当前的方法定义将覆盖超类中的方法。 |
---|
@Deprecated:如果程序员使用了注解为它的元素,那么编译器会发出警告信息。 |
@SuppressWarnings:关闭不当的编译器警告信息。在java SE5之前的版本中,也可以使用该注解,不过会被忽略不起作用。 |
元注解
@Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括: ElemenetType.CONSTRUCTOR——————————————-构造器声明 ElemenetType.FIELD —————————————————域声明(包括 enum 实例) ElemenetType.LOCAL_VARIABLE————————————- 局部变量声明 ElemenetType.METHOD ————————————————-方法声明 ElemenetType.PACKAGE ————————————————包声明 ElemenetType.PARAMETER ———————————————参数声明 ElemenetType.TYPE—————————————————- 类,接口(包括注解类型)或enum声明 |
---|
@Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括: RetentionPolicy.SOURCE——————-注解将被编译器丢弃 RetentionPolicy.CLASS ——————-注解在class文件中可用,但会被VM丢弃 RetentionPolicy.RUNTIME ————-VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。 |
@Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当于@see,@param 等。 ** |
@Inherited 允许子类继承父类中的注解。 |
**
@interface
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
代码示例
1.创建自定义注解,我这里的自定义注解用于数据字典添加或更新时做一个Redis的同步数据更新。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DictCacheManager {
String desc();
// 如果为true,需要使用response当做参数
boolean isUseResponse() default false;
}
2.添加自定义注解
@RestController
@RequestMapping("/v2/dictionary")
public class DictionaryController {
@DubboReference(check = true)
private IV2DictionaryService IV2DictionaryService;
@Autowired
private DictCacheOperator dictCacheOperator;
@PostMapping("/add")
@DictCacheManager(desc = "新增字典")
public ResponseData add(@RequestBody Dictionary dictionary) {
return ResponseData.success(IV2DictionaryService.addDictionary(dictionary));
}
}
3.使用AOP拦截,并进行业务逻辑处理
@Slf4j
@Aspect
@Component
public class DictCacheManagerAspect {
@Autowired
private DictCacheOperator dictCacheOperator;
//使用@annotation用于拦截@DictCacheManager注解
@AfterReturning(value = "@annotation(producer)", returning = "response")
public void doAfterReturning(JoinPoint joinPoint, ResponseData response, DictCacheManager producer) {
log.info("send msg to redis start.");
boolean isUseResponse = producer.isUseResponse();
Object[] requestDataArr = joinPoint.getArgs();
Object requestData = requestDataArr.length > 0 ? requestDataArr[0] : new Object();
if (!ResponseData.DEFAULT_SUCCESS_CODE.equals(response.getCode())) {
// 如果不是成功,直接返回
return;
}
Object data = isUseResponse ? response.getData() : requestData;
if (ToolUtil.isEmpty(data)) {
return;
}
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 0L, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<>(5));
threadPoolExecutor.execute(() -> dictCacheOperator.cache(data));
}
}
4.处理Redis业务逻辑
@Component
@Slf4j
public class DictCacheOperator {
@Autowired
private RedisService redisService;
@DubboReference(check = true)
private IV2DictionaryService dictionaryService;
public void cache(Object data) {
// 添加或修改字典
if (data instanceof Dictionary) {
Dictionary dictionary = (Dictionary) data;
Dictionary queryDict = dictionaryService.queryDictionaryByCode(dictionary.getCode());
DictItem dictItem = buildDictItem(dictionary);
redisService.set(DICT_CACHE_KEY.concat(queryDict.getCode()), dictItem);
}
// 删除字典
if (data instanceof List) {
List<String> deleteCodes = CommonUtil.castList(data, String.class);
deleteCodes.forEach(code -> {
if (redisService.hasKey(DICT_CACHE_KEY.concat(code))) {
redisService.del(DICT_CACHE_KEY.concat(code));
}
});
}
}
}