5

我在一个项目中使用 Netty (4.0.4.Final),并且我一直遇到我需要排除的循环依赖。这个问题主要涉及分解循环依赖的概念,但我会为熟悉的人使用一些 Netty 术语。不过,由于我的问题实际上与 Netty 无关,所以我决定不标记它。

下面,我发布了我的代码,省略了我认为不相关的部分。

情况

我有一个MyServer将 a 添加ChannelInboundHandlerAdapter到 a的类Bootstrap

public class MyServer extends AbstractMyServer {
    private Integer someInteger; //Using Integer just for example's sake.

    public MyServer(MyServerInitializer initializer) {
        //...
        bootstrap.handler(initializer);
        //...
    }

    public void updateInteger(Integer value) {
        someInteger = value;
        //Send an update packet to another server.
    }
}

MyServerInitializer需要添加ChannelInboundHandlerAdapter一个ChannelPipeline

public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
    private ChannelInboundHandlerAdapter handler;

    public MyServerInitializer(ChannelInboundHandlerAdapter handler) {
        this.handler = handler;
    }

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline().addLast(
                new ObjectEncoder(),
                new ObjectDecoder(),
                handler);
    }
}

在我正在谈论的情况下,我还有一个MyServerHandlerwhich 是构造函数参数:MyServerInitializer

public class MyServerHandler extends ChannelInboundHandlerAdapter {
    private MyServer server;

    public MyServerHandler(MyServer server) {
        this.server = server;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Integer obj = (Integer) msg; //Remember just using Integer for example. Think of it as an Object rather than an Integer.
        server.updateInteger(obj);
    }
}

因此,循环依赖在初始化期间变得明显:

public static void main(String[] args) {
    //I can't set a reference to MyServer instance here because it hasn't been created yet. I want to avoid the circular dependency here.
    MyServerHandler handler = new MyServerHandler(...);
    MyServerInitializer initializer = new MyServerInitializer(handler);
    MyServer server = new MyServer(initializer);
}

可能的解决方案

重构为main()

我可以拉出 ofInteger someIntegerMyServer创建,在main()函数范围内创建它,然后将它的引用注入到MyServerHandlerandMyServer中。这当然MyServerHandler可以直接修改它,而不必通过MyServer. 缺点是它已在main()现在的范围内声明。我不想对每个可能本质上需要由类修改的类成员执行此操作Handler

创建一个MyServerFactory

我读到的其中一个概念是将构造与使用分开。这很有意义,所以我试了一下下面的工厂模式实现。

public class MyServerFactory implements AbstractFactory<MyServer> {
    public MyServer create() {
        Integer someInteger = createInteger();
        MyServerHandler handler = createHandler(someInteger);
        MyServerInitializer initializer = createInitializer(handler);
        return new MyServer(initializer);
    }

    /* creator methods for the different components above. */
}

但是,这似乎我只是将代码从main()这个Factory类中移了出来。

问题

  1. 如果我想注入不同的东西会发生什么Handler-MyServerInitializer也许这个新Handler的不接受 anInteger作为论点。我必须Factory为这种情况创建一个新的吗?
  2. 拥有一个Factory可能只会创建单个实例的MyServer?
  3. 是否有其他选项可用于排除此循环参考?

粗体字是我在 StackOverflow 上提出这个问题的主要焦点。我觉得我必须在这里忽略一些更简单或更优雅的东西。我希望你们中一些更有经验的用户可以提供一些见解。请让我知道是否需要更多信息。

参考资料

4

1 回答 1

0

免责声明:我对 Netty 了解不多,这些只是阅读您的代码的一些想法:

我看不出有什么问题MyServerInitializer。对orMyServerInitializer没有任何依赖关系。没关系。如果 的构造函数需要而不是.MyServerHandlerMyServerMyServerInitializerMyServerHandlerChannelInboundHandlerAdapter

如果可能,您应该将MyServerfrom的构造函数参数更改MyServerInitializerChannelInitializer<SocketChannel>

问题在于,MyServerHandler取决于MyServerwhileMyServerMyServerHandler. 我会尝试摆脱MyServer. MyServerHandler为此,您可以:

  • updateInteger()方法从MyServer另一个类中移动,我们称之为IntegerUpdater. MyServerHandler应该使用IntegerUpdater而不是MyServer. IntegerUpdater应该不依赖于MyServer. 使用这种方式,您将不会有任何循环依赖。

  • MyServerHandler在和之间添加一个抽象MyServer。例如:

    public interface IntegerMessageReceiver {
      void handleMessage(Integer i);
    }
    

-

    public class MyServerHandler extends ChannelInboundHandlerAdapter {
      private List<IntegerMessageReceiver> integerMessageReceivers;

      public void addIntegerMessageReceiver(IntegerMessageReceiver imr) {
        integerMessageReceivers.add(imr);
      }

      @Override
      public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Integer obj = (Integer) msg; 
        for (IntegerMessageReceiver imr : integerMessageReceivers) { 
          imr.handleMessage(obj);
        }
      }
    }

-

    public class MyServer extends AbstractMyServer implements IntegerMessageReceiver {
      public void handleMessage(Integer i) {
        ...
      }
      ...
    }

初始化:

MyServerHandler handler = new MyServerHandler();
MyServerInitializer initializer = new MyServerInitializer(handler);
MyServer server = new MyServer(initializer);
handler.addIntegerMessageReceiver(server);

使用这种方法,你仍然会有循环运行时依赖,但至少你摆脱了 in 的直接编译时MyServer依赖MyServerHandler

于 2013-08-03T22:59:52.157 回答