netty-Netty中pipeline设计模式的一个高仿示例

 

下属是一个Netty中pipeline设计模式的高仿示例。下述代码中:Channel对应netty中的AbstractChannel, AbstractContext对应netty中的 AbstractChannelHandlerContext , Inhander对应netty中的ChannelInboundHandler,OutHandler对应netty中的ChannelOutboundHandler,Initializer对应netty中的ChannelInitializer, ChannelPipeLine对应netty中的DefaultChannelPipeline,测试的main方法在Channel中。感兴趣的同学可以拷贝运行代码,并对照netty源码研究。

Context:
public interface Context {


    public Handler handler();




}
AbstractContext:
public abstract class AbstractContext implements Context {

    volatile AbstractContext next;
    volatile AbstractContext prev;

    private final boolean inbound;
    private final boolean outbound;
    private final ChannelPipeLine pipeline;
    private final String name;


    public AbstractContext(String name, ChannelPipeLine pipeline, boolean inbound, boolean outbound) {
        this.inbound = inbound;
        this.outbound = outbound;
        this.name = name;
        this.pipeline = pipeline;
    }

    public ChannelPipeLine pipeline() {
        return pipeline;
    }

    public Channel channel() {
        return pipeline.channel();
    }

    public String getName() {
        return name;
    }


    private AbstractContext findContextInbound() {
        AbstractContext ctx = this;
        do {
            ctx = ctx.next;
        } while (!ctx.inbound);
        return ctx;
    }

    private AbstractContext findContextOutbound() {
        AbstractContext ctx = this;
        do {
            ctx = ctx.prev;
        } while (!ctx.outbound);
        return ctx;
    }


    public void request() {
        final AbstractContext next = findContextOutbound();
        next.invokeRequest();
    }



    private void invokeRequest() {
        OutHandler outhandler = (OutHandler)handler();
        outhandler.request(this);
    }


    public void response() {
        final AbstractContext next = findContextInbound();
        next.invokeResponse();

    }


    private void invokeResponse() {
        InHandler inhandler = (InHandler)handler();
        inhandler.response(this);
    }

    public void register() {
        AbstractContext contextInbound = findContextInbound();
        contextInbound.invokeRegister();

    }

    private void invokeRegister() {
        InHandler inhandler = (InHandler)handler();
        inhandler.register(this);

    }

}

DefaultContext:
public class DefaultContext extends AbstractContext {

    private Handler handler;

    public DefaultContext(String name, ChannelPipeLine pipeline, Handler handler) {
        super(name, pipeline, isInbout(handler), isOutbound(handler));
        this.handler = handler;
    }



    @Override
    public Handler handler() {
        return handler;
    }

    private static boolean isInbout(Handler handler) {
        return handler instanceof InHandler;
    }

    private static boolean isOutbound(Handler handler) {
        return handler instanceof OutHandler;
    }
}
Handler:
public interface Handler {




}
InHandler:
public interface InHandler extends Handler {

    public void response(AbstractContext ctx);

    public void register(AbstractContext ctx);

}

OutHandler:
 
public interface OutHandler extends Handler {

    public void request(AbstractContext ctx);

}

HeadCtx:
public class HeadCtx extends AbstractContext implements OutHandler {

    public HeadCtx(ChannelPipeLine pipeline) {
        super("Head", pipeline, false, true);
    }

    @Override
    public Handler handler() {
        return this;
    }


    @Override
    public void request(AbstractContext ctx) {
        System.out.println("head connect method is called!!!");
       /* ChannelPipeLine pipeLine = getPipeline();
        pipeLine.response();*/
    }


    public void fireRegister() {
    }
}

TailCtx:
public class TailCtx extends AbstractContext implements InHandler {

    public TailCtx(ChannelPipeLine pipeline) {
        super("Tail", pipeline, true, false);
    }



    @Override
    public Handler handler() {
        return this;
    }


    @Override
    public void response(AbstractContext ctx) {

        System.out.println("taill response is called !!!");
       /* ChannelPipeLine pipeline = getPipeline();
        pipeline.request();*/
    }


    @Override
    public void register(AbstractContext ctx) {
    }
}

ChannelPipeLine:
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger;

public class ChannelPipeLine {


    private Channel channel;
    final AbstractContext head;
    final AbstractContext tail;
    final AtomicInteger inCounter = new AtomicInteger(0);
    final AtomicInteger outCounter = new AtomicInteger(0);


    public ChannelPipeLine(Channel channel) {

        this.channel = channel;
        head = new HeadCtx(this);
        tail = new TailCtx(this);

        head.next = tail;
        tail.prev = head;
    }

    public Channel channel() {
        return channel;
    }



    public final AbstractContext context(Handler handler) {
        if (handler == null) {
            throw new NullPointerException("handler");
        }

        AbstractContext ctx = head.next;
        for (;;) {

            if (ctx == null) {
                return null;
            }

            if (ctx.handler() == handler) {
                return ctx;
            }

            ctx = ctx.next;
        }
    }


    public final ChannelPipeLine remove(Handler handler) {
        remove(getContextOrDie(handler));
        return this;
    }

    private AbstractContext getContextOrDie(Handler handler) {
        AbstractContext ctx =  context(handler);
        if (ctx == null) {
            throw new NoSuchElementException(handler.getClass().getName());
        } else {
            return ctx;
        }
    }


    private AbstractContext remove(final AbstractContext ctx) {
        assert ctx != head && ctx != tail;

        synchronized (this) {
            remove0(ctx);
        }
        return ctx;
    }

    private static void remove0(AbstractContext ctx) {
        AbstractContext prev = ctx.prev;
        AbstractContext next = ctx.next;
        prev.next = next;
        next.prev = prev;
    }


    public ChannelPipeLine addLast(Handler handler) {

        DefaultContext newCtx = null;
        if (handler instanceof OutHandler) {

            newCtx = new DefaultContext("OutHandler#" + inCounter.getAndAdd(1), this, handler);

        } else if (handler instanceof InHandler) {

            newCtx = new DefaultContext("InHandler#" + outCounter.getAndAdd(1), this, handler);

        } else {
            throw new IllegalArgumentException("handler must be InHandler or OutHandler");
        }
        addLast0(newCtx);
        return this;
    }

    private void addLast0(AbstractContext newCtx) {
        AbstractContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;
    }


    public void request() {
        tail.request();
    }

    public void response() {
        head.response();
    }


    public ChannelPipeLine register() {
        head.register();
        return this;
    }







}

Initializer:
public abstract class Initializer implements InHandler {

    private String name = "initializer";

    @Override
    public void response(AbstractContext ctx) {
    }


    @Override
    public void register(AbstractContext ctx) {
        initChannel(ctx);
        ctx.register();
    }


    private void initChannel(AbstractContext ctx) {
        try {
            Channel channel = ctx.channel();
            initChannel(channel);
        } finally {
            remove(ctx);
        }
    }


    public abstract void initChannel(Channel channel);


    private void remove(AbstractContext ctx) {
        ChannelPipeLine pipeline = ctx.pipeline();
        if (pipeline.context(this) != null) {
            pipeline.remove(this);
        }
    }
}

Channel:
public class Channel {

    private ChannelPipeLine pipeLine;

    public Channel() {
        this.pipeLine = new ChannelPipeLine(this);
    }

    public ChannelPipeLine pipeLine() {
        return this.pipeLine;
    }

    public static void main(String[] args) {
        Handler inHandler1 = new InHandler() {
            private String name = "InHandler1";

            @Override
            public void response(AbstractContext ctx) {
                System.out.println("InHandler1 response called !!!");
                ctx.response();
            }

            @Override
            public void register(AbstractContext ctx) {
                System.out.println("inHandler 1 register called !!!");
                ctx.register();

            }
        };

        Handler outHandler1 = new OutHandler() {
            private String name = "OutHandler1";

            @Override
            public void request(AbstractContext ctx) {
                System.out.println("OutHandler1 connect called !!!");
                ctx.request();
            }
        };

        Handler inHandler2 = new InHandler() {
            private String name = "InHandler2";

            @Override
            public void response(AbstractContext ctx) {
                System.out.println("InHandler2 response called !!!");
                ctx.response();
            }

            @Override
            public void register(AbstractContext ctx) {
                System.out.println("inHandler 2 register called !!!");
                ctx.register();
            }
        };

        Handler outHandler2 = new OutHandler() {
            private String name = "OutHandler2";

            @Override
            public void request(AbstractContext ctx) {
                System.out.println("OutHandler2 connect called !!!");
                ctx.request();
            }
        };

        Channel channel = new Channel();
        ChannelPipeLine pipeLine = channel.pipeLine();
        pipeLine.addLast(new Initializer() {
            @Override
            public void initChannel(Channel channel) {
                ChannelPipeLine pipeLine = channel.pipeLine();
                pipeLine.addLast(inHandler1);
                pipeLine.addLast(outHandler1);
                pipeLine.addLast(inHandler2);
                pipeLine.addLast(outHandler2);
            }
        });


        pipeLine.register();

        System.out.println("add done !!!");
        System.out.println();

        System.out.println("out bount event start !!!");
        pipeLine.request();
        System.out.println();


        System.out.println("in bount event start !!!");
        pipeLine.response();
    }


}

 





  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值