2016-11-13 2 views
1

У меня есть приложение с Spring и Netty. Проблема в том, что я пытаюсь интегрировать обе структуры таким образом, чтобы обработчик Netty был уникальным для каждого канала.Spring and Netty

Таким образом, компонент, который инициализирует сервер Нетти выглядит следующим образом:

@Component 
public class TCPServer { 

... 

@Autowired 
@Qualifier("messageHandler") 
private MessageHandler messageHandler; 

private Channel serverChannel; 

public void start() throws Exception { 
    logger.info("Starting TCP Server..."); 
    ServerBootstrap b = new ServerBootstrap(); 
    final EventExecutorGroup customGroup = new DefaultEventExecutorGroup(100); 

    b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) 
    .childHandler(new ChannelInitializer<SocketChannel>() { 
     @Override 
     protected void initChannel(SocketChannel channel) throws Exception { 
      ChannelPipeline pipeline = channel.pipeline(); 
      pipeline.addLast(new Encoder()); 
      pipeline.addLast(new Decoder()); 
      pipeline.addLast(customGroup, messageHandler); 
     } 
    }); 
    Set<ChannelOption<?>> keySet = tcpChannelOptions.keySet(); 
    for (@SuppressWarnings("rawtypes") ChannelOption option : keySet) { 
     b.option(option, tcpChannelOptions.get(option)); 
    } 

    serverChannel = b.bind(tcpPort).sync().channel(); 
    logger.info("TCP Server started."); 
} 
... 
} 

и обработчик:

@Component 
@Sharable 
public class MessageHandler extends SimpleChannelInboundHandler<Message> { 

@Autowired 
private ChannelRepository channelRepository; 

private CommandUtil commandUtil; 

@Override 
public void channelActive(ChannelHandlerContext ctx) throws Exception { 

    channelRepository.put(channelKey, ctx.channel()); 
    commandUtil = new CommandUtil(); 
    ctx.channel().attr(AttributeKey.valueOf("commands")).set(commandUtil); 

} 
... 
} 

Это прекрасно работает, но проблема заключается в том, что Нетти создает только один экземпляр MessageHandler класса и если я заменил введенный MessageHandler и каждый раз ставил новый экземпляр (new MessageHandler()) Я теряю контекст Spring - channelRepository - null.

Вопрос в том, как я могу реализовать новый экземпляр MessageHandler для каждого канала и не потерять контекст Spring (использовать поля с автоподстановкой)?

ответ

2

Создайте завод для вашего MessageHandler. Вставьте ChannelRepository на свой завод и введите завод в свой ChannelInitializer (TCPServer).

Удалить @Sharable из MessageHandler, что предотвратит случайное использование одного и того же в нескольких каналах. Вы должны добавить только эту аннотацию, если безопасно использовать один и тот же обработчик по каналам.

+0

Как получить доступ к «ChannelRepository» в «MassageHandler»? – Nikola

+0

Добавьте конструктор в MessageHandler и передайте его с фабрики в создаваемый экземпляр –