mina-过滤器Iofilter的设计
转载:http://www.iteye.com/topic/1124504
二、Mina是怎么实现责任链模式的
上面介绍了纯净的责任链模式,但是在真实的项目中写代码不可能完全照搬,所以多看看开源项目的代码写作方式也许才能真正提高我们的编程能力。就以Mina的过滤器链来看,对这种模式进行了自己的实现,但是道理是相通的,带着责任链模式的理解去看看Mina的实现是怎样的。
先看一下Mina过滤器的类图结构:
从图中我们可以看出Mina对于此模式的实现是相对比较复杂的,其实从它的代码上也可以看出来,当时也是花了好大力气才把它这块看明白,其实主要在于理清思路,抓住核心类,最主要的一个接口IoFilterChain和它的一个内部接口Entry,其中IoFilterChain代表了过滤器的容器,它本身就是一个对象引用形成的链表结构,默认的实现DefaultIoFilterChain其实有对链表头(head)的引用,找到头后就可以顺着头向下找,一直找到尾(tail),Entry是对IoFilter和NextFilter的封装整合接口,它属于链表IoFilterChain中的元素。指向当前和下一个过滤器。
EntryImpl 类中包含两个接口,filter和nextFilter,他们所用的接口是不一样的,至于为什么不用同一个接口,我想可能是因为接口职责单一的原则吧。
虽然有IoFilter和NextFilter两个接口,接口方法都差不多,但最后真正业务的执行者还是IoFilter的实现,IoFilterAdapter做为它的默认实现,完成了适配器的功能,以后的类可以直接继承它而不用实现IoFilter接口,想实现哪个方法只需要覆盖IoFilterAdapter的类的方法即可。NextFilter只起到转发的作用,如消息接收处理方法(messageReceived):
NextFilter的实现:
- //消息接收到以后NextFilter的实现会把消息传递给nextEntry去处理。
- public void messageReceived(IoSession session, Object message) {
- Entry nextEntry = EntryImpl.this.nextEntry;
- callNextMessageReceived(nextEntry, session, message);
- }
DefaultIoFilterChain再将消息传递给本Filter的messageReceived方法进行实际的消息接收处理工作:
- private void callNextMessageReceived(Entry entry, IoSession session,
- Object message) {
- try {
- IoFilter filter = entry.getFilter();
- NextFilter nextFilter = entry.getNextFilter();
- //本过滤器进行数据处理,完成后再把消息传向下个过滤器
- filter.messageReceived(nextFilter, session,
- message);
- } catch (Throwable e) {
- fireExceptionCaught(e);
- }
- }
当消息处理完成以后,消息就要进入到业务处理IoHandler的实现类中去完成业务的相关操作了。这可以在链尾看到相关业务传递:
- @Override
- public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
- AbstractIoSession s = (AbstractIoSession) session;
- if (!(message instanceof IoBuffer)) {
- s.increaseReadMessages(System.currentTimeMillis());
- } else if (!((IoBuffer) message).hasRemaining()) {
- s.increaseReadMessages(System.currentTimeMillis());
- }
- try {
- // 最后一个filter会进入到handler进行消息处理。
- session.getHandler().messageReceived(s, message);
- } finally {
- if (s.getConfig().isUseReadOperation()) {
- s.offerReadFuture(message);
- }
- }
- }
至此,Mina的链表结构就基本讲完了,其实仔细看看它的代码还是比较容易理解的,可能里面有些细节还需要我们去琢磨。
链表建立了以后,外界是怎样调用的呢?
在org.apache.mina.core.filterchain包下我们可以看到类IoFilterEvent,可以看到它实现了基于事件的处理模型,当一个事件(比如接收到消息)发生后会触发相应的事件,进而调用过滤器链的消息处理功能进行消息的处理和转发,这块其实会有线程池的参与完成,会在以后的文章中说明这块。
- public void fire() {
- IoSession session = getSession();
- NextFilter nextFilter = getNextFilter();
- IoEventType type = getType();
- if (DEBUG) {
- LOGGER.debug( "Firing a {} event for session {}",type, session.getId() );
- }
- switch (type) {
- case MESSAGE_RECEIVED:
- //触发消息接收
- Object parameter = getParameter();
- nextFilter.messageReceived(session, parameter);
- break;
当然也可以直接调用:
- //触发过滤器的接收消息处理
- session.getFilterChain().fireMessageReceived(newBuf);
还有一个类DefaultIoFilterChainBuilder,它以用户更易用的角度完成了对过滤器链的封装操作,这里就不细讲了。
总结:本文章主要讲了责任链模式在Mina中的实现,做为一个优秀的框架我们没理由不好好去学习。
每天进步一点点,不做无为的码农。。。。。