參考官方文檔:https://dromara.org/zh-cn/doc...html
引入相關依賴(官方示例默認開啓的alibaba-dubbo,具體參考:soul-examples-dubbo)java
soul-bootstrap
新增以下依賴:git
<!--soul apache dubbo plugin start--> <dependency> <groupId>org.dromara</groupId> <artifactId>soul-spring-boot-starter-plugin-apache-dubbo</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>2.7.5</version> </dependency> <!-- Dubbo zookeeper registry dependency start --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-client</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.0.1</version> </dependency> <!-- Dubbo zookeeper registry dependency end -->
soul-examples-apache-dubbo-service
新增以下依賴:github
<!--soul apache dubbo plugin start--> <dependency> <groupId>org.dromara</groupId> <artifactId>soul-spring-boot-starter-plugin-apache-dubbo</artifactId> <version>2.2.1</version> </dependency> <!--soul apache dubbo plugin end--> <!-- Dubbo dependency --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>2.7.5</version> </dependency> <!-- Dubbo zookeeper registry dependency start--> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.5.6</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> <!-- Dubbo zookeeper registry dependency end -->
application.yml
添加相關配置spring
soul: dubbo: adminUrl: http://localhost:9095 contextPath: /dubbo appName: dubbo # adminUrl: 爲你啓動的soul-admin 項目的ip + 端口,注意要加 http:// # contextPath: 爲你的這個項目在soul網關的路由前綴,好比/order ,/product 等等,網關會根據你的這個前 綴來進行路由. # appName:你的應用名稱,不配置的話,會默認取 dubbo配置中application 中的名稱
dubbo 插件設置數據庫
soul-admin
插件管理中,dubbo
插件設置爲開啓
apache
dubbo
插件中配置你的註冊地址
bootstrap
接口註冊到網關緩存
@SoulDubboClient
註解,表示該接口方法註冊到網關zk
,而後再啓動TestApacheDubboApplication
,輸出日誌 dubbo client register success
,表示dubbo
接口已經發布到 soul 網關服務在啓動時會將類方法上的 @SoulDubboClient
註解註冊到網關,接下來分析一下@SoulDubboClient
註冊邏輯。app
soul-examples-apache-dubbo-service
添加了soul-spring-boot-starter-plugin-apache-dubbo
依賴,註冊邏輯應該就在這個自定義的spring-boot-starter
中。
首先註釋掉DubboTestServicel
類中findById
方法上的@SoulDubboClient
註解
@Override //@SoulDubboClient(path = "/findById", desc = "Query by Id") public DubboTest findById(final String id) { DubboTest dubboTest = new DubboTest(); dubboTest.setId(id); dubboTest.setName("hello world Soul Apache, findById"); return dubboTest; }
soul-spring-boot-starter-client-apache-dubbo 自定義spring-boot-starter
經過 spring.factories 加載了SoulApacheDubboClientConfiguration
類:
@Configuration public class SoulApacheDubboClientConfiguration { /** * Apache dubbo service bean post processor alibaba dubbo service bean post processor. * * @param dubboConfig the dubbo config * @return the alibaba dubbo service bean post processor */ @Bean public ApacheDubboServiceBeanPostProcessor apacheDubboServiceBeanPostProcessor(final DubboConfig dubboConfig) { return new ApacheDubboServiceBeanPostProcessor(dubboConfig); } /** * Dubbo config dubbo config. * * @return the dubbo config */ @Bean @ConfigurationProperties(prefix = "soul.dubbo") public DubboConfig dubboConfig() { return new DubboConfig(); } }
SoulApacheDubboClientConfiguration
加載了ApacheDubboServiceBeanPostProcessor
實例,該實例實現了ApplicationListener<ContextRefreshedEvent>
接口,該類中的主要方法:
public ApacheDubboServiceBeanPostProcessor(final DubboConfig dubboConfig) { //獲取 application.yml 文件中的配置信息 String contextPath = dubboConfig.getContextPath(); String adminUrl = dubboConfig.getAdminUrl(); if (StringUtils.isEmpty(contextPath) || StringUtils.isEmpty(adminUrl)) { throw new RuntimeException("apache dubbo client must config the contextPath, adminUrl"); } this.dubboConfig = dubboConfig; url = dubboConfig.getAdminUrl() + "/soul-client/dubbo-register"; executorService = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); }
@Override public void onApplicationEvent(final ContextRefreshedEvent contextRefreshedEvent) { if (Objects.nonNull(contextRefreshedEvent.getApplicationContext().getParent())) { return; } // Fix bug(https://github.com/dromara/soul/issues/415), upload dubbo metadata on ContextRefreshedEvent //根據 beanType 獲取全部的 bean,這裏獲取的是 spring-dubbo.xml 中 <dubbo:service/>中的DubboTestService和 //DubboMultiParamService //ServiceBean.class:org.apache.dubbo.config.spring.ServiceBean.class Map<String, ServiceBean> serviceBean = contextRefreshedEvent.getApplicationContext().getBeansOfType(ServiceBean.class); for (Map.Entry<String, ServiceBean> entry : serviceBean.entrySet()) { executorService.execute(() -> handler(entry.getValue())); } }
處理類中的每一個方法
private void handler(final ServiceBean serviceBean) { Class<?> clazz = serviceBean.getRef().getClass(); if (ClassUtils.isCglibProxyClass(clazz)) { String superClassName = clazz.getGenericSuperclass().getTypeName(); try { clazz = Class.forName(superClassName); } catch (ClassNotFoundException e) { log.error(String.format("class not found: %s", superClassName)); return; } } // 獲取類中每一個方法 final Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(clazz); for (Method method : methods) { //獲取類上的 @SoulDubboClient 註解 SoulDubboClient soulDubboClient = method.getAnnotation(SoulDubboClient.class); if (Objects.nonNull(soulDubboClient)) { //遠程調用,註冊方法信息到 soul-admin RegisterUtils.doRegister(buildJsonParams(serviceBean, soulDubboClient, method), url, RpcTypeEnum.DUBBO); } } }
當獲取到DubboTestServicel
類中findById
的方法時,因爲咱們上面註釋了 @SoulDubboClient
註解,全部以這裏獲取 SoulDubboClient 的值爲 null。
至此,@SoulDubboClient
註解分析完畢
先記錄一個問題,明天再看:soul 的數據同步是將數據庫中的信息同步到本地緩存中,若是是已經經過 @SoulDubboClient
註解註冊到soul-admin
的方法被刪除了,數據庫中的信息何時刪除?例如上面findById
方法已經註釋掉了 @SoulDubboClient
註解,服務重啓時輸出的註冊信息已經沒有了findById
方法,可是soul-admin
中dubbo 插件列表和元數據列表中依然存在findById
方法信息。