文章目录
问题缘由
起因是设计一款RPC框架,但是客户端由于只有接口,没有实现,所以加入Spring不能实现。因此和分享小组成员讨论研究,最后得到自己想要的是什么。
gitee地址:https://gitee.com/kylin1991_admin/rpc_handwriting
快速开始
1、加入maven包
-
加入jar
reflections
-可以选择不加入,我只是为了扫包方便(后面可以自己写扫描)<!-- https://mvnrepository.com/artifact/org.reflections/reflections --> <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.11</version> <exclusions> <exclusion> <groupId>javassist</groupId> <artifactId>javassist</artifactId> </exclusion> </exclusions> </dependency>
-
Spring-context 这个需要的,因为我们要用容器和注解和bean
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.4.RELEASE</version> </dependency>
2、写一个自己的FactoryBean
-
例如:我是要实现动态代理,自己写了一个
public class FactoryRpcClientBean<T> implements FactoryBean<T> { private Class<T> interfaceType; private String host; private int port; public FactoryRpcClientBean(Class<T> interfaceType, String host, int port) { // 构造器的参数可以自己定义, // 只需要在beanDefinition注册的时候传递过来即可 this.interfaceType = interfaceType; this.host = host; this.port = port; } @Override public T getObject() throws Exception { // 这里主要是创建接口对应的实例,便于注入到spring容器中 // 所以这里也是控制实例的结果的。 return new RpcProxyClient().proxyClient(interfaceType, host, port); } @Override public Class<T> getObjectType() { // 这里是控制类型,同时也可以根据这个类型来获取bean return interfaceType; } @Override public boolean isSingleton() { return true; } }
3、干预BeanDefinition
-
只需要注意bean的注册和需要什么参数就行了,其他忽略(是我个人的框架需要而已)
@Configuration public class SpringConfig implements BeanDefinitionRegistryPostProcessor { private static final String host = "localhost"; private static final int port = 8080; private static final String SCANNER_PATH = "org.example"; @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { // 扫描xx路径下的@注解的接口或类 Reflections reflections = new Reflections(SCANNER_PATH); Set<Class<?>> set = reflections.getTypesAnnotatedWith(RpcClient.class); for (Class<?> aClass : set) { // 通过FactoryRpcClientBean来生成一个新的BeanDefinition BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FactoryRpcClientBean.class); BeanDefinition definition =builder.getRawBeanDefinition(); // 传入构造参数 definition.getConstructorArgumentValues().addGenericArgumentValue(aClass); definition.getConstructorArgumentValues().addGenericArgumentValue(host); definition.getConstructorArgumentValues().addGenericArgumentValue(port); // 注册BeanDefinitionBuilder beanDefinitionRegistry.registerBeanDefinition(aClass.getSimpleName(), definition); } } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { } }
上面已经完成,可以直接使用了
下面就是加入自己的注解,不过和上面没多大关系了
1、自定义Autowired注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Autowired
public @interface RpcClient {
}