Netty注解实现服务调用
在之前完成了原生服务间的简单通信,现在我们将它整合到Spring环境中,这里就以实现服务的远程调用,简单模拟即可,具体代码需要自己动手改造。
既然是服务调用,那我们就使用代理模式来实现。
新建代理类,这里简单上送个参数和方法名即可,服务端响应不做处理,你理解我的目的就行
public class JdkProxy implements InvocationHandler {
private Object target;
public JdkProxy(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Protocol<RequestMsg> protocol = new Protocol<>();
protocol.setMsgType((short)1);
RequestMsg requestMsg = new RequestMsg();
requestMsg.setMsg("方法:"+method.getName());
requestMsg.setOther("参数:"+args[0]);
protocol.setBody(requestMsg);
//Protocol<ResponseMsg> responseMsgProtocol = NettyClient.getInstance().sendMsg(protocol);
MyFuture myFuture = NettyClient.getInstance().sendMsg(protocol);
return myFuture.get().toString();
}
}
代理类创建模板
public class MyNettyClient {
public <T> T create(Class<T> clz){
return (T)Proxy.newProxyInstance(clz.getClassLoader(),new Class[]{clz},new JdkProxy(clz));
}
}
将模板注入到spring中
@Configuration
public class ClientConfig {
@Bean
MyNettyClient myNettyClient(){
MyNettyClient instance = new MyNettyClient();
return instance;
}
}
查看实现效果
每次使用都还要先获取代理对象,很麻烦,代码升级,实现注解直接调用
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Autowired
public @interface MyAn {
}
@Component
public class MyAnBean implements FactoryBean<Object> {
private Class<?> interfaceClass;
public Class<?> getInterfaceClass() {
return interfaceClass;
}
public void setInterfaceClass(Class<?> interfaceClass) {
this.interfaceClass = interfaceClass;
}
private Object object;
@Override
public Object getObject() throws Exception {
return object;
}
@Override
public Class<?> getObjectType() {
return interfaceClass;
}
public void init () throws Exception{
MyNettyClient myNettyClient = new MyNettyClient();
this.object = myNettyClient.create(interfaceClass);
}
}
@Component
public class MyAnConfig implements ApplicationContextAware,BeanClassLoaderAware,BeanFactoryPostProcessor {
private static final Logger logger = LoggerFactory.getLogger(MyAnConfig.class);
private ApplicationContext context;
private ClassLoader classLoader;
private final Map<String,BeanDefinition> myAnDefinitions = new ConcurrentHashMap<>();
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for(String beanDefinitionName:beanFactory.getBeanDefinitionNames()){
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName);
String beanClassName = beanDefinition.getBeanClassName();
if(beanClassName!=null){
Class<?> clazz = ClassUtils.resolveClassName(beanClassName, this.classLoader);
ReflectionUtils.doWithFields(clazz,this::parseMyAn);
}
}
BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
this.myAnDefinitions.forEach((beanName,beanDefinition)->{
if (context.containsBean(beanName)){
throw new IllegalArgumentException("spring context already has a bean named "+ beanName);
}
registry.registerBeanDefinition(beanName,myAnDefinitions.get(beanName));
logger.info("registered ReferenceBean {} success",beanName);
});
}
private void parseMyAn(Field field) {
MyAn annotation = AnnotationUtils.getAnnotation(field, MyAn.class);
if(annotation!=null){
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyAnBean.class);
builder.setInitMethodName("init");
builder.addPropertyValue("interfaceClass",field.getType());
BeanDefinition beanDefinition = builder.getBeanDefinition();
myAnDefinitions.put(field.getName(),beanDefinition);
}
}
}
这样是不是很高级的感觉了呢