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 !