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 protocol = new Protocol<>();
        protocol.setMsgType((short)1);
        RequestMsg requestMsg = new RequestMsg();
        requestMsg.setMsg("方法:"+method.getName());
        requestMsg.setOther("参数:"+args[0]);
        protocol.setBody(requestMsg);
        Protocol responseMsgProtocol = NettyClient.getInstance().sendMsg(protocol);
        return responseMsgProtocol.getBody().toString();
    }
}

代理类创建模板

public class MyNettyClient {

    public  T create(Class 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;
    }
}

查看实现效果
Netty注解实现服务调用_第1张图片
每次使用都还要先获取代理对象,很麻烦,代码升级,实现注解直接调用

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Autowired
public @interface MyAn {
}
@Component
public class MyAnBean implements FactoryBean {

    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 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);
        }
    }
}

Netty注解实现服务调用_第2张图片
这样是不是很高级的感觉了呢

你可能感兴趣的:(java)