ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

RPC代理实现

2021-09-23 09:04:20  阅读:118  来源: 互联网

标签:String 实现 代理 private public method RPC new class


RPC代理实现

目的

以调用 java 接口方式请求 http, 如:

@RpcClient(name = "helloService ")
public interface HelloService {

    String say(String msg);
}

当调用 helloService.say 时直接请求 其他服务http 接口

定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(RpcClientsRegistrar.class)
public @interface EnableRcpComponentScan {

    @AliasFor("basePackages")
    String[] value() default {};

    String[] basePackages() default {};

    Class<?>[] clients() default {};
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface RpcClient {

    String name();

}

扫描注解


public class RpcClientsRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware, ResourceLoaderAware {

    private Environment environment;
    private ResourceLoader resourceLoader;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {

        //1. 扫描EnableRcpComponentScan bean
        LinkedHashSet<BeanDefinition> components = new LinkedHashSet<>();
        Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(EnableRcpComponentScan.class.getName());

        Class<?>[] clients = (Class<?>[]) attributes.get("clients");
        if (clients == null || clients.length == 0) {

            ClassPathScanningCandidateComponentProvider scanner = getScanner();
            scanner.setResourceLoader(resourceLoader);
            scanner.addIncludeFilter(new AnnotationTypeFilter(RpcClient.class));
            Set<String> packages = getScanPackages(attributes);

            for (String basePackage : packages) {
                components.addAll(scanner.findCandidateComponents(basePackage));
            }
        } else {

            for (Class<?> client : clients) {
                components.add(new AnnotatedGenericBeanDefinition(client));
            }
        }

        //注册bean
        for (BeanDefinition component : components) {
            if (component instanceof AnnotatedBeanDefinition) {
                AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) component;
                AnnotationMetadata metadata = beanDefinition.getMetadata();
                Assert.isTrue(metadata.isInterface(), "RpcClient should be a interface");

                Map<String, Object> attrs = metadata.getAnnotationAttributes(RpcClient.class.getName());
                String name = (String) attrs.get("name");

                // 注册 @RpcClient
                registerRpcClient(registry, beanDefinition, attrs);

            }
        }

    }

    private void registerRpcClient(BeanDefinitionRegistry registry, 
    		AnnotatedBeanDefinition annotatedBeanDefinition, Map<String, Object> attrs) {
        String name = (String) attrs.get("name");
        AnnotationMetadata metadata = annotatedBeanDefinition.getMetadata();
        String className = metadata.getClassName();
        Class clz = ClassUtils.resolveClassName(className, null);
        RpcClientFactoryBean factoryBean = new RpcClientFactoryBean();
        factoryBean.setClz(clz);
        factoryBean.setName(name);

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clz,
        	 () -> {
            return factoryBean.getObject();
        });

        beanDefinitionBuilder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        beanDefinitionBuilder.setLazyInit(true);
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, className);
        beanDefinition.setAttribute("setFactoryBeanName factoryBean", factoryBean);

        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className);
        BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);

    }

    /**
     * 获取 扫描 package
     *
     * @param attributes
     * @return
     */
    private Set<String> getScanPackages(Map<String, Object> attributes) {
        Set<String> basePackages = new LinkedHashSet<>();
        String[] values = (String[]) attributes.get("value");
        for (String value : values) {
            if (StringUtils.hasText(value)) {
                basePackages.add(value);
            }
        }

        String[] pkgs = (String[]) attributes.get("basePackages");
        for (String pack : pkgs) {
            if (StringUtils.hasText(pack)) {
                basePackages.add(pack);
            }
        }
        return basePackages;
    }

    private ClassPathScanningCandidateComponentProvider getScanner() {
        return new ClassPathScanningCandidateComponentProvider(false, environment) {
            @Override
            protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                boolean isCandidate = false;
                if (beanDefinition.getMetadata().isIndependent()) {
                    if (!beanDefinition.getMetadata().isAnnotation()) {
                        isCandidate = true;
                    }
                }
                return isCandidate;
            }
        };
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}

通过FactoryBean 获取代理类

public class RpcClientFactoryBean implements FactoryBean<Object> {

    @Setter
    private Class<?> clz;

    @Setter
    private String name;

    @Override
    public Object getObject() {
        return getTarget();
    }

    /**
     * 返回代理类
     *
     * @param <T>
     * @return
     */
    private <T> T getTarget() {
        return new RpcClientTarget(clz).target();
    }


    @Override
    public Class<?> getObjectType() {
        return clz;
    }

}

public class RpcClientInvocationHandler implements InvocationHandler {

    private RpcClientTarget rpcClientTarget;
    private Map<String, RpcMethodHandler> dispatchers;

    public RpcClientInvocationHandler(RpcClientTarget rpcClientTarget, Map<String, RpcMethodHandler> map) {
        this.rpcClientTarget = rpcClientTarget;
        this.dispatchers = map;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return dispatchers.get(method.getName()).invoke(args);
    }
}

public class RpcClientTarget {

    private RpcMethodHandlerFactory factory = new RpcMethodHandlerFactory();
    private Class clz;

    public RpcClientTarget(Class clz) {
        this.clz = clz;
    }

    public <T> T target() {
        // 1.遍历 class 中所有 public 方法
        Map<String, RpcMethodHandler> map = new HashMap<>();
        for (Method method : clz.getMethods()) {
            if (method.getDeclaringClass() == Object.class) {
                continue;
            } else {
                map.put(method.getName(), factory.create(method));
            }
        }
        // 2.为每个方法创建代理
        InvocationHandler invocationHandler = new RpcClientInvocationHandler(this, map);
        T proxy = (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[]{clz}, invocationHandler);
        return proxy;
    }
}

代理方法

public interface RpcMethodHandler {

    Object invoke(Object[] args);

}

public class RpcMethodHandlerFactory {

    public RpcMethodHandler create(Method method) {
        return new SyncRpcMethodHandler(method);
    }
}

public class SyncRpcMethodHandler implements RpcMethodHandler {

    private Method method;

    public SyncRpcMethodHandler(Method method) {
        this.method = method;
    }

    @Override
    public Object invoke(Object[] args) {
        // TODO: 2021/9/22 rpc request...
        //做一些 http 请求 and so on..
        String argss = Arrays.stream(args)
                .map(arg -> (String) arg).collect(Collectors.joining(","));
        return method.getName() + ": " + argss;
    }

}

使用方式

启动类加入 @EnableRcpComponentScan:

@EnableRcpComponentScan(basePackages = {"com.bootmvc.service"})
public class BootMvcApplication {

    public static void main(String[] args) {
        SpringApplication.run(BootMvcApplication.class, args);
    }

}

测试

@SpringBootTest
public class HelloServiceTest {

    @Autowired
    private HelloService helloService;

    @Test
    public void helloTest() {

        String hello = helloService.say("good");
        System.out.println(hello);

        String nihao = helloService.say("你好");
        System.out.println(nihao);

        String say = helloService.say("lala", "小明");
        System.out.println(say);

    }
}

//结果
say: good
say: 你好
say: lala,小明

good luck !

标签:String,实现,代理,private,public,method,RPC,new,class
来源: https://blog.csdn.net/u013887008/article/details/120427607

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有