最近建了个技术交流群,然后好多小伙伴都问关于Netty的问题,尤其今天的问题最特殊,功能大概是要在Netty接收消息时把数据写入数据库,那个小伙伴用的是 Spring Boot + MyBatis + Netty,所以就碰到了Handler中@Autowired注解为空的问题
参考了一些大神的博文,Spring Boot非controller使用@Autowired注解注入为null的问题,得到结论:
首先改造一下Application,实现ApplicationContextAware接口,这里这样写是考虑到使用完还要释放,所以写的比较复杂
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@SpringBootApplication
public class SpbNettyApplication implements ApplicationContextAware {
private static ApplicationContext applicationContext;
private static DefaultListableBeanFactory defaultListableBeanFactory;
public static void main(String[] args) {
SpringApplication.run(SpbNettyApplication.class, args);
new EchoServer().start(1234);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
defaultListableBeanFactory = (DefaultListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();
}
public static
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
String className = clazz.getName();
defaultListableBeanFactory.registerBeanDefinition(className, beanDefinitionBuilder.getBeanDefinition());
return (T) applicationContext.getBean(className);
}
public static void destroy(String className){
defaultListableBeanFactory.removeBeanDefinition(className);
System.out.println("destroy " + className);
}
}
这时候就可以在Netty的Handler中为所欲为啦!
import com.avanty.spbnetty.pojo.Car;
import com.avanty.spbnetty.service.CarServiceImpl;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class EchoHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) {
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg){
System.out.println(ctx.channel().remoteAddress() + " " + msg.toString());
ctx.channel().write("recv : " + msg.toString());
ctx.channel().flush();
Car car = new Car();
car.setCarBrand("Mustang");
car.setCarNum("789632");
CarServiceImpl carServiceImpl = SpbNettyApplication.getBean(CarServiceImpl.class);
carServiceImpl.addCar(car);
SpbNettyApplication.destroy(CarServiceImpl.class.getName());
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
System.out.println("offline " + ctx.channel().remoteAddress());
}
}