前几天写了一个消息中间件(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. [Oracle整理]ORA-12705(字符集问题)

    [Oracle整理]ORA-12705(字符集问题)   2017年5月11日 18:11 [Oracle整理]ORA-12705(字符集问题) 说明:本内容是工作用到的知识点整理,来自工作中和网络. ...

  2. 【计算机视觉】SIFT中LoG和DoG比较

    <SIFT原理与源码分析>系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html 在实际计算时,三种方法计算的金字塔组数noctaves ...

  3. linux内核支持nfs挂载配置

    1.配置网络部分,主要是使能CONFIG_IP_PNP以在2中能够看到Root file system on NFS选项Networking support Networking options TC ...

  4. 第2章-Vue.js指令

    一.学习目标 了解 什么 是 Vue.js 指令 理解 Vue.js 指令的 用途 掌握 Vue.js 指令的书写规范 能够 使用 Vue.js 指令完成部门页面交互效果(难点和重点) 二.指令的基本 ...

  5. Ubuntu+NDK编译支持HTTPS的libcurl

    参考文章:1.NDK环境配置 http://blog.csdn.net/smfwuxiao/article/details/65877092.libcurl的配置修改 http://piggyq.co ...

  6. OpenCV---超大图像二值化和空白区域过滤

    超大图像的二值化方法 1.可以采用分块方法, 2.先缩放处理就行二值化,然后还原大小 一:分块处理超大图像的二值化问题 def big_image_binary(image): print(image ...

  7. .Net平台下实例类型无法转换成接口类型?

    首先这种情况出现在应用程序启动前的方法里面. 本想通过发射来实现一些功能.谁知道被这个坑了. 碰到这种问题.已经相当无语了.同时也不知道该如何解决.望有能之士帮忙解答 using System; us ...

  8. JS笔记-强化版2

    1.DOM:   DOM : Document Object Model 文档对象模型 文档:html页面 文档对象:页面中元素 文档对象模型:定义 为了能够让程序(js)去操作页面中的元素   DO ...

  9. ③ 设计模式的艺术-09.组合(Composite)模式

    使用组合模式的场景 类图当中有三个类,一个是Component(节点的统一接口),它的目的是为了统一节点的操作.接下来的两个实现类,一个则是非叶子节点(Composite),它可以有子节点.另外一个则 ...

  10. java用于控制可见性的4个访问修饰符

    仅对本类可见——private 对所有类可见——public 对本包的所有子类可见——protected 对本包可见——默认(很遗憾)不需要修饰符