前几天写了一个消息中间件(kafka)的封装,业务方发现消费者需要配置的东西太多(每增加一个topic和实现类都需要在配置文件中加,会显得很繁琐)。于是我为了尽量减少这个XML配置,采用注解的方式来获取topic和实现类。

第一步:先自定义一个注解,有一个topic的方法用于表明需要监听的topic

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
public @interface TopicSub {
TopicType topic() ;
}

第二步:获取所有使用该注解的类以及注解值

 List<MessageContainer> messageContainerList= Lists.newArrayList();
Map<String, Object> maps= SpringBeanUtils.getAnnotation(TopicSub.class);
for (Map.Entry<String, Object> entry : maps.entrySet()) {
TopicSub topicAnn = entry.getValue().getClass().getAnnotation(TopicSub.class);
MessageContainer messageContainer=new MessageContainer(topicAnn.topic().getName());
messageContainer.setMessageHandle((MessageListener)entry.getValue());
messageContainerList.add(messageContainer);
}

特别说明:SpringBeanUtils.getAnnotation(TopicSub.class)是调用ApplicationContext容器的 getBeansWithAnnotation(Class<? extends Annotation> var1)方法,返回的是所有使用该注解的bean

然后遍历这个map,拿到每个bean上的注解值(topic方法的值);这里拿bean的注解值的方式是反射.getClass().getAnnotation(),如果bean是放在被代理的包下(service包下一般都是被事务代理了,AOP的实现就是JDK(CJLIB)动态代理),那么.getClass().getAnnotation()这个方法是拿不到注解值的,因为.getClass()拿到的是代理类而不是真正的类,建议这些实现类放在一个不被代理的包下(就是建立一个普通的package即可),如果放在代理包下,那就需要先获取真正的bean,再反射。

三、监听到消息后,根据topic的值调用实现类

  for (MessageContainer messageContainer : PropertyFactory.consumerProperty.getMessageContainers()) {
if (consumerRecord.topic().equals(messageContainer.getTopic())) {
try {
messageContainer.getMessageHandle().onMessage(consumerMessageBO);
}catch (KafkaComsumException e){
}
}

四、业务方实现类

@Component
@TopicSub(topic = TopicType.SMS_ASYNC_SEND)
public class SmsMessageHandler implements MessageListener{
public static final Logger log= LoggerFactory.getLogger(SmsMessageHandler.class);
@Autowired
private SmsSendLogDao smsSendLogDao;
public void onMessage(ConsumerMessageBO consumerMessageBO) throws KafkaComsumException{
log.info(JSONObject.toJSONString(consumerMessageBO));
try {
SmsMessageEO message =JSONObject.parseObject(consumerMessageBO.getMessage().toString(),SmsMessageEO.class);
for(String phone:message.getPhone() ){
SmsResult result= SmsUtils.sendSms(phone,message.getContent(),message.getProduct());
SmsSendLogDO smsSendLogDO=new SmsSendLogDO();
smsSendLogDO.setContent(message.getContent());
smsSendLogDO.setPhone(phone);
smsSendLogDO.setProduct(message.getProduct());
smsSendLogDO.setCreateTime(new Date());
smsSendLogDO.setStatus(result.getCode()==1?1:0);
smsSendLogDO.setSender(message.getSender().getName());
smsSendLogDao.insert(smsSendLogDO);
}
}catch (Exception e){
throw new KafkaComsumException();
} } }

前三步都是在jar包中完成(对业务方是透明的),业务方只需要完成第四步消息实现类的逻辑即可(不需要任何xml的配置),有没有感觉很清爽啊!

这样我们就进一步提升了中间件解耦的程度,其实也满简单的,唯一的坑就是AOP中反射获取到的是代理类这个问题,也是小伙伴们需要注意的!

spring自定义注解的使用的更多相关文章

  1. spring自定义注解实现登陆拦截器

    1.spring自定义注解实现登陆拦截器 原理:定义一个注解和一个拦截器,拦截器拦截所有方法请求,判断该方法有没有该注解.没有,放行:有,要进行验证.从而实现方法加注解就需要验证是否登陆. 2.自定义 ...

  2. spring - 自定义注解

    本自定义注解的作用:用于控制类方法的调用,只有拥有某个角色时才能调用. java内置注解 1.@Target 表示该注解用于什么地方,可能的 ElemenetType 参数包括: ElemenetTy ...

  3. Spring 自定义注解,配置简单日志注解

    java在jdk1.5中引入了注解,spring框架也正好把java注解发挥得淋漓尽致. 下面会讲解Spring中自定义注解的简单流程,其中会涉及到spring框架中的AOP(面向切面编程)相关概念. ...

  4. 照虎画猫写自己的Spring——自定义注解

    Fairy已经实现的功能 读取XML格式配置文件,解析得到Bean 读取JSON格式配置文件,解析得到Bean 基于XML配置的依赖注入 所以,理所当然,今天该实现基于注解的依赖注入了. 基于XML配 ...

  5. 使用Spring自定义注解实现任务路由的方法

    在Spring mvc的开发中,我们可以通过RequestMapping来配,当前方法用于处理哪一个URL的请求.同样我们现在有一个需求,有一个任务调度器,可以按照不同的任务类型路由到不同的任务执行器 ...

  6. Spring自定义注解扫描的实现

    目标:实现自定义spring自动扫描注解.主要为后期实现分布式服务框架自动注解提供技术支持 技术分析:通过配置组件扫描标签使spring解析标签. 1. JewelScanBeanDefaultPar ...

  7. 2018-02-11 发布 spring 自定义注解(annotation)与 aop获取注解

    知识点: Java自定义注解.spring aop @aspect的使用 首先我们先介绍Java自定义注解. 在开发过程中,我们实现接口的时候,会出现@Override,有时还会提示写@Suppres ...

  8. 深入Spring:自定义注解加载和使用

    前言 在工作中经常使用Spring的相关框架,免不了去看一下Spring的实现方法,了解一下Spring内部的处理逻辑.特别是开发Web应用时,我们会频繁的定义@Controller,@Service ...

  9. 【转】spring 自定义注解(annotation)与 aop获取注解

    首先我们先介绍Java自定义注解. 在开发过程中,我们实现接口的时候,会出现@Override,有时还会提示写@SuppressWarnings.其实这个就是Java特有的特性,注解. 注解就是某种注 ...

  10. Spring 自定义注解,结合AOP,配置简单日志注解 (转)

    java在jdk1.5中引入了注解,spring框架也正好把java注解发挥得淋漓尽致. 下面会讲解Spring中自定义注解的简单流程,其中会涉及到spring框架中的AOP(面向切面编程)相关概念. ...

随机推荐

  1. git使用笔记(十三)ls-files

    By francis_hao    Mar 18,2018   git ls-fles 显示index和工作区的文件的信息. 概要 git ls-files [-z] [-t] [-v]        ...

  2. R-FCN:基于区域的全卷积网络来检测物体

    http://blog.csdn.net/shadow_guo/article/details/51767036 原文标题为“R-FCN: Object Detection via Region-ba ...

  3. Android Monkey 脚本编写与检查内存泄露

    一.Monkey脚本编写 1.Monkey脚本格式 脚本优势: 简单快捷,不需要接触任何工具,只需要一个记事本文件 脚本缺点: 实现坐标.按键等基本操作的相应步骤,顺序脚本无逻辑性 脚本源码: \de ...

  4. java project转变成java web project

    首先,你的eclipse必须得装有web插件 1.找到项目工作空间目录,打开.project文件,并修改文件, 修改如下:      找到:<natures> </natures&g ...

  5. Tensorflow BatchNormalization详解:4_使用tf.nn.batch_normalization函数实现Batch Normalization操作

    使用tf.nn.batch_normalization函数实现Batch Normalization操作 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 吴恩达deeplearnin ...

  6. JS笔记-强化版1

    1.函数:可以理解为-命令,做一些事~~       function abc(){ // 肯定不会主动执行的!       ……       }       直接调用:abc();       事件 ...

  7. 关于java 获取 html select标签 下拉框 option 文本内容 隐藏域

    在HTML中从多选下拉框中提取已选中选项的文本内容到后台,被这个问题难倒了. demo.jsp文件 <select id="selecttype" name"typ ...

  8. js javascript变量提升

    var:变量提升(无论声明在何处,都会被提至其所在作用域的顶部) let:无变量提升(所在的块内,未到let声明时(即let声明之前),是无法访问该变量的(not defined)),let变量不能重 ...

  9. LintCode 391: Count Of Airplanes

    LintCode 391: Count Of Airplanes 题目描述 给出飞机的起飞和降落时间的列表,用 interval 序列表示. 请计算出天上同时最多有多少架飞机? 样例 对于每架飞机的起 ...

  10. Gmail登录(2017.10)

    本文地址:http://www.cnblogs.com/veinyin/p/7646382.html  由于众所周知的原因,我们使用 Gmail 查看邮件时会有些麻烦,有时梯子不够用甚至不能查看. 比 ...