未验证 提交 864991d5 编写于 作者: S SnailClimb 提交者: GitHub

Merge pull request #3 from MrBigThree/master

客户端整合spring
......@@ -15,4 +15,6 @@
/.settings
*/.settings
.classpath
.project
\ No newline at end of file
.project
Target/
*.iml
\ No newline at end of file
package github.javaguide;
import github.javaguide.api.Hello;
import github.javaguide.api.HelloService;
import lombok.extern.slf4j.Slf4j;
/**
......
package github.javaguide;
import github.javaguide.api.HelloService;
import github.javaguide.remoting.transport.netty.server.NettyServer;
/**
......
package github.javaguide;
import github.javaguide.api.HelloService;
import github.javaguide.remoting.transport.socket.SocketRpcServer;
/**
......
package github.javaguide;
package github.javaguide.api;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.*;
import java.io.Serializable;
......
......@@ -32,6 +32,7 @@
<module>example-client</module>
<module>example-server</module>
<module>rpc-framework-common</module>
<module>rpc-framework-spring</module>
</modules>
<dependencies>
<!-- lombok -->
......
......@@ -19,5 +19,6 @@ public class ZkServiceRegistry implements ServiceRegistry {
//根节点下注册子节点:服务
String servicePath = CuratorUtils.ZK_REGISTER_ROOT_PATH + "/" + serviceName + inetSocketAddress.toString();
CuratorUtils.createPersistentNode(servicePath);
}
}
# 整合spring
基于spring 5.2.6.RELEASE
- 通过一个注解就可以实现远程接口的调用
@RpcServiceScan("github.javaguide.api")
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>guide-rpc-framework</artifactId>
<groupId>github.javaguide</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>rpc-framework-spring</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>github.javaguide</groupId>
<artifactId>rpc-framework-simple</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>github.javaguide</groupId>
<artifactId>hello-service-api</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package github.javaguide;
import github.javaguide.proxy.RpcClientProxy;
import github.javaguide.remoting.transport.ClientTransport;
import github.javaguide.remoting.transport.netty.client.NettyClientTransport;
/**
* @description: 简单写一个方法获取代理对象,其实应该在simple框架里面提供一个接口获取代理对象
* @author:lvxuhong
* @date:2020/6/18
*/
public class ClientProxy {
public static <T> T getServiceProxy(Class<T> serviceClass) {
ClientTransport rpcClient = new NettyClientTransport();
RpcClientProxy rpcClientProxy = new RpcClientProxy(rpcClient);
return rpcClientProxy.getProxy(serviceClass);
}
}
package github.javaguide.spring.annotation;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
/**
* @description:
* @author:lvxuhong
* @date:2020/6/18
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RpcServiceScannerRegistrar.class)
public @interface RpcServiceScan {
String value();
}
package github.javaguide.spring.annotation;
import github.javaguide.spring.rpcservice.RpcServiceScanner;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
/**
* @description:
* @author:lvxuhong
* @date:2020/6/18
*/
public class RpcServiceScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
private ResourceLoader resourceLoader;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(RpcServiceScan.class.getName()));
RpcServiceScanner scanner = new RpcServiceScanner(registry);
String value = annoAttrs.getString("value");
if (resourceLoader != null) {
scanner.setResourceLoader(resourceLoader);
}
//所有的接口全部注入
scanner.addIncludeFilter(new TypeFilter() {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) {
return true;
}
});
scanner.doScan(value);
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
}
package github.javaguide.spring.rpcservice;
import github.javaguide.ClientProxy;
import org.springframework.beans.factory.FactoryBean;
/**
* @description:
* @author:lvxuhong
* @date:2020/6/18
*/
public class RpcServiceFactoryBean<T> implements FactoryBean<T> {
private Class<T> rpcServiceInterface;
public RpcServiceFactoryBean() {
}
public RpcServiceFactoryBean(Class<T> rpcServiceInterface) {
this.rpcServiceInterface = rpcServiceInterface;
}
@Override
public T getObject() throws Exception {
if (rpcServiceInterface == null) {
throw new IllegalStateException("");
}
return ClientProxy.getServiceProxy(rpcServiceInterface);
}
@Override
public Class<?> getObjectType() {
return rpcServiceInterface;
}
@Override
public boolean isSingleton() {
return false;
}
}
package github.javaguide.spring.rpcservice;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import java.util.Arrays;
import java.util.Set;
/**
* @description:
* @author:lvxuhong
* @date:2020/6/18
*/
public class RpcServiceScanner extends ClassPathBeanDefinitionScanner {
private RpcServiceFactoryBean<Object> rpcServiceFactoryBean = new RpcServiceFactoryBean<>();
public RpcServiceScanner(BeanDefinitionRegistry registry) {
super(registry);
}
@Override
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
//父类在扫描的时候 beanDefinition 会通过 registry 注册,我们需要修改 beanDefinition 的 beanClass
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
processBeanDefinitions(beanDefinitions);
return beanDefinitions;
}
/**
* 主要是将beanDefinition 的beanClass 设置成我们自定义的FactoryBean
*
* @param beanDefinitions
*/
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
GenericBeanDefinition definition;
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitions) {
definition = (GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
definition.setBeanClass(rpcServiceFactoryBean.getClass());
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
}
/**
* {@inheritDoc}
*/
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
}
}
package github.javaguide.spring;
import github.javaguide.api.Hello;
import github.javaguide.api.HelloService;
import github.javaguide.spring.annotation.RpcServiceScan;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
/**
* @description:
* @author:lvxuhong
* @date:2020/6/19
*/
public class ClientTest {
@Test
public void test() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(TestConfig.class);
applicationContext.refresh();
applicationContext.start();
HelloService helloService = applicationContext.getBean(HelloService.class);
Hello hello = Hello.builder().message("test message").description("test description").build();
String res = helloService.hello(hello);
String expectedResult = "Hello description is " + hello.getDescription();
Assert.assertEquals(expectedResult, res);
}
//@Configuration
@RpcServiceScan("github.javaguide.api")
public static class TestConfig {
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册