利用Spring事件机制改善原有代码

不积跬步,无以至千里;不积小流,无以成江海

前些时间,在图书馆借阅了《重构-改善既有代码的设计》这本书,书中列举的代码中的坏味道,不就是自己平时写过的代码吗?

话不多说,先上一段伪代码,有什么问题吗?

public Result addMessage() throws Exception{
    	//此处省略n行代码
    	//发短信
    	smsUtil.sendSms();
    	//消息推送
        jpushUtils.sendClient();
        //发送微信
        ...
    	return ResultUtil.success();
    }

确实没问题,是能够正常运行的。不过,如果现在要增加发送微信的功能,去掉消息推送呢?也很简单,添加一个发送微信的方法,然后再注释掉消息推送的方法。但是,这样真的好吗?

六大设计原则

  • 单一职责原则

    一个类只负责一个功能领域中的相应职责。高内聚、低耦合。

  • 开闭原则

    对扩展开放,对修改关闭。不修改原有代码的情况下进行扩展。

  • 里氏代换原则

    所有引用基类(父类)的地方必须能透明地使用其子类的对象。

  • 依赖倒转原则

    抽象不应该依赖于细节,细节应当依赖于抽象。

  • 接口隔离原则

    接口拆分,当一个接口太大时,我们需要将它分割成一些更细小的接口。

  • 迪米特法则

    减少依赖,一个软件实体应当尽可能少地与其他实体发生相互作用。

很显然,上面的修改方式已经违背了单一职责和开闭原则。有没有什么办法呢,其实Spring为我们提供了事件通知机制。

ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。

观察者模式

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。又称:发布/订阅、消息通知机制 、事件监听、事件驱动编程。
接下来,利用观察者模式设计高拓展性的代码,利用spring事件机制改造消息处理功能:

事件监听类

/**
 * 事件监听类
 */
public class ConfigEvent extends ApplicationEvent {
    public ConfigEvent(Object source) {
    	//source:传入的参数
        super(source);
    }
}

监听ConfigEvent事件

/**
 * 发送短信
 */
@Component
public class SmsListener implements ApplicationListener<ConfigEvent> {

    @Override
    public void onApplicationEvent(ConfigEvent configEvent) {
        System.out.println("2:短信发送成功!" + configEvent.getSource());
    }
}
@Component
public class WeChatListener implements ApplicationListener<ConfigEvent> {

    @Override
    public void onApplicationEvent(ConfigEvent configEvent) {
        System.out.println("3:微信发送成功!" + configEvent.getSource());
    }
}

消息处理类

/**
 * 消息处理
 */
@Service
public class MessageService{

    @Resource
    private ApplicationContext applicationContext;

    public void addMessage() {
    	//业务
        System.out.println("1:消息添加成功");
        ConfigEvent configEvent = new ConfigEvent("内容:857857");
        //事件发布
        applicationContext.publishEvent(configEvent);
    }
}

测试方法

	@Autowired
    private MessageService messageService;

    @Test
    public void Test() {
        messageService.addMessage();
    }
打印结果:
1:消息添加成功
2:短信发送成功!内容:857857
3:微信发送成功!内容:857857

这样修改后,即使再增加发送邮件,也只需要增加一个类去监听原有事件,而不用去修改原有的代码,便于后期的扩展和维护。

Spring内置事件

  1. ApplicationContextEvent

    spring内置事件的父抽象类,构造方法传入spring的context容器,同时也有获取spring的context容器的方法。

  2. ContextRefreshedEvent

    当spring容器初始化或刷新时,会触发此事件。此事件在开发中常用,用于在spring容器启动时,导入自定义的bean实例到spring容器中。

  3. ContextStartedEvent

    当spring启动时,或者说是context调用start()方法时,会触发此事件。

  4. ContextStoppedEvent

    当spring停止时,或者说context调用stop()方法时,会触发此事件。

  5. ContextClosedEvent

    当spring关闭时,或者说context调用close()方法时,会触发此事件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

予润

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值