文章目錄
問題緣由
起因是設計一款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 {
}