我在一个项目中使用Netty(4.0.4.Final),并且我一直在遇到一个我需要考虑的循环依赖。这个问题主要涉及分解循环依赖的概念,但我会在熟悉的人中使用一些Netty术语。既然我的问题实际上并不在于Netty,我决定不对其进行标记。
下面,我发布了我的代码,省略了我认为不相关的部分。
我有一个MyServer
课程,为ChannelInboundHandlerAdapter
添加了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);
}
}
我还有一个MyServerHandler
,这是我所说的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()
我可以从Integer someInteger
中创建MyServer
,在main()
函数的范围内创建它,然后将其引用注入MyServerHandler
和{{1} }}。这当然会让MyServer
能够直接修改它,而不必通过MyServerHandler
。缺点是它现在已在MyServer
范围内声明。我不想为每个可能基本上需要由main()
类修改的类成员执行此操作。
Handler
我读到的一个概念是将构造与使用分开。这很有道理,所以我用下面的Factory模式实现了它。
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
注入不同的Handler
会发生什么 - 也许这个新MyServerInitializer
不接受Handler
作为参数。我是否必须为此案例创建一个新的Integer
? Factory
有可能只创建Factory
的单个实例是否有意义?粗体问题是我在StackOverflow上提出这个问题的主要焦点。我觉得我必须在这里忽略更简单或更优雅的东西。我希望你们中的一些更有经验的用户可以提供一些见解。如果需要更多信息,请告诉我。
答案 0 :(得分:0)
免责声明:我对Netty了解不多,这些只是阅读您的代码时的一些想法:
我认为MyServerInitializer
没有任何问题。 MyServerInitializer
或MyServerHandler
没有任何依赖关系MyServer
。没关系。如果MyServerInitializer
的构造函数需要MyServerHandler
而不是ChannelInboundHandlerAdapter
,情况会更糟。
如果可能,您应该将MyServer
的构造函数参数从MyServerInitializer
更改为ChannelInitializer<SocketChannel>
。
问题在于MyServerHandler
取决于MyServer
而MyServer
对MyServerHandler
具有间接运行时依赖性。我会尝试摆脱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);
使用这种方法你仍然会有循环的运行时依赖性,但至少你摆脱了MyServer
中MyServerHandler
的直接编译时依赖性。