使用@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)@Documentedpublic @interface DictCacheManager {String desc();// 如果为true,需要使用response当做参数boolean isUseResponse() default false;}
2.添加自定义注解
@RestController@RequestMapping("/v2/dictionary")public class DictionaryController {@DubboReference(check = true)private IV2DictionaryService IV2DictionaryService;@Autowiredprivate DictCacheOperator dictCacheOperator;@PostMapping("/add")@DictCacheManager(desc = "新增字典")public ResponseData add(@RequestBody Dictionary dictionary) {return ResponseData.success(IV2DictionaryService.addDictionary(dictionary));}}
3.使用AOP拦截,并进行业务逻辑处理
@Slf4j@Aspect@Componentpublic class DictCacheManagerAspect {@Autowiredprivate 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@Slf4jpublic class DictCacheOperator {@Autowiredprivate 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));}});}}}
