本文主要介紹如何進行發布和引用JVM服務,包括下述 2 部分:
發布和引用 JVM 服務的 3 種方式。包括:
XML 方式
XML 的配置路徑是在服務發布和引用類所在模塊的 resources/META-INF/spring
下。默認沒有 spring 文件夾,需要新建。新建 XML 文件時,所需的 schema 請從 resources 下默認生成的 XML 中拷貝。
服務發布
操作步驟示例如下:
配置一個 Bean:
<bean id="sampleService" class="com.alipay.sofa.runtime.test.service.SampleServiceImpl">
通過 SOFA 提供的 Spring 擴展標簽將上面的 Bean 發布成一個 JVM 服務。
<sofa:service interface="com.alipay.sofa.runtime.test.service.SampleService" ref="sampleService"> <sofa:binding.jvm/> </sofa:service>
說明interface 指的是需要發布成服務的接口。
ref 指向的是需要發布成 JVM 服務的 Bean。
服務引用
操作步驟示例如下:
使用 Spring 擴展標簽引用服務:
<sofa:reference interface="com.alipay.sofa.runtime.test.service.SampleService" id="sampleServiceRef"> <sofa:binding.jvm/> </sofa:reference>
說明interface:是服務的接口,需要和發布服務時配置的 interface 一致。
id:上述配置會生成一個 id 為 sampleServiceRef 的 Spring Bean。
service 與 reference 標簽還支持 RPC 服務發布,可參考 RPC 服務發布與引用。
將這個 Bean 注入到當前 SOFABoot 模塊 Spring 上下文的任意地方。
Annotation 方式
除了通過 XML 方式發布 JVM 服務和引用之外,SOFABoot 還提供了 Annotation 的方式來發布和引用 JVM 服務。
服務發布
使用方式在實現類上加一個 @SofaService
注解,對于該注解,說明如下:
如果一個服務已經被加上了
@SofaService
的注解,它就不能再用 XML 的方式去發布服務了。兩種方式不能混用。@SofaService
的作用是將一個 Bean 發布成一個 JVM 服務。接口支持
單接口:當被
@SofaService
注解的類只有一個接口的時候,框架會直接采用這個接口作為服務的接口。多接口:當被
@SofaService
注解的類實現了多個接口時,可以設置@SofaService
的interfaceType
字段來指定服務接口。
類注解和方法注解
類注解:在實現類上打上
@SofaService
注解,則在 Spring Boot 使用 Bean Method 創建 Bean 時,會導致@Bean
和@SofaService
分散在兩處,而且無法對同一個實現類使用不同的 uniqueId。方法注解:自 SOFABoot 2.6.0 版本起,支持
@SofaService
作用在 Bean Method 之上。
示例上述說明示例如下:
單接口實現
@SofaService public class SampleImpl implements SampleInterface{ public void test(){ } }
多接口實現
@SofaService(interfaceType=SampleInterface.class) public class SampleImpl implements SampleInterface,Serializable{ public void test(){ } }
方法注解
@Configuration public class SampleSofaServiceConfiguration{ @Bean("sampleSofaService") @SofaService(uniqueId ="service1") SampleService service(){ return new SampleServiceImpl(""); } }
服務引用
使用方式在引用類里,使用 @SofaReference
注解,對于該注解,說明如下:
@SofaReference
在不指定服務接口時,會采用被注解字段的類型作為服務接口。可以通過設定
@SofaReference
的interfaceType
屬性來指定服務接口。自 SOFABoot 2.6.0 版本起,支持在 Bean Method 參數上使用
@SofaReference
注解引用 JVM 服務。
示例上述說明示例如下:
單接口實現
public class SampleServiceRef{ @SofaReference private SampleService sampleService; }
多接口實現
public class SampleServiceRef{ @SofaReference(interfaceType=SampleService.class) private SampleService sampleService; }
方法注解
@Configuration public class MultiSofaReferenceConfiguration { @Bean("sampleReference") TestService service(@Value("$spring.application.name") String appName, @SofaReference(uniqueId = "service") SampleService service) { return new TestService(service); } }
編程 API 方式
SOFABoot 為 JVM 服務的發布和引用提供了一套編程 API 方式,方便直接在代碼中發布和引用 JVM 服務。
服務發布
使用步驟示例如下:
首先需要實現
ClientFactoryAware
接口獲取編程組件 API:public class ClientFactoryBean implements ClientFactoryAware { private ClientFactory clientFactory; @Override public void setClientFactory(ClientFactory clientFactory) { this.clientFactory = clientFactory; } }
使用
clientFactory
通過編程 API 方式發布 JVM 服務:ServiceClient serviceClient = clientFactory.getClient(ServiceClient.class); ServiceParam serviceParam =new ServiceParam(); serviceParam.setInstance(new SampleServiceImpl()); serviceParam.setInterfaceType(SampleService.class); serviceClient.service(serviceParam);
代碼說明
通過
clientFactory
獲得ServiceClient
對象。構造
ServiceParam
對象,其包含發布服務所需參數。通過
setInstance
方法來設置需要被發布成 JVM 服務的對象通過
setInterfaceType
來設置服務的接口。
調用
ServiceClient
的service
方法,發布一個 JVM 服務。
服務引用
使用步驟示例如下:
首先需要實現
ClientFactoryAware
接口獲取編程組件 API。參見 服務發布。使用
clientFactory
通過編程 API 方式發布 JVM 服務:ReferenceClient referenceClient = clientFactory.getClient(ReferenceClient.class); ReferenceParam<SampleService> referenceParam =new ReferenceParam<SampleService>(); referenceParam.setInterfaceType(SampleService.class); SampleService proxy = referenceClient.reference(referenceParam);
代碼說明
從
ClientFactory
中獲取一個ReferenceClient
。與發布一個服務類似,構造出一個
ReferenceParam
。設置好服務的接口。
調用
ReferenceClient
的reference
方法。通過動態客戶端創建的
Reference
對象是一個非常重的對象,使用時不要頻繁創建,自行做好緩存,否則可能存在內存溢出的風險。
uniqueId 配置方式
有些場景,針對一個接口,可能會需要發布兩個服務,分別對應到不同的實現。此時,可以通過配置 uniqueId 來區分不同的實現。下文主要講述 uniqueId 在下述 3 中方式中的配置:
下文示例:sampleService
有兩個 SampleService
的實現,且這兩個實現都需要發布成 JVM Service。
在 xml 中配置
配置步驟示例如下:
服務發布時加入 uniqueId:
<sofa:service interface="com.alipay.sofa.runtime.test.service.SampleService" ref="sampleService1"unique-id="ss1"> </sofa:service> <sofa:service interface="com.alipay.sofa.runtime.test.service.SampleService" ref="sampleService2"unique-id="ss2"> </sofa:service>
引用服務時,通過指定 uniqueId 區分不同服務:
如要使用
sampleService1
的服務,可指定unique-id
為ss1
,例如:<sofa:reference interface="com.alipay.sofa.runtime.test.service.SampleService"id="sampleService"unique-id="ss1"> </sofa:reference>
如要使用
sampleService2
的服務,可指定unique-id
為ss2
,例如:<sofa:reference interface="com.alipay.sofa.runtime.test.service.SampleService"id="sampleService"unique-id="ss2"> </sofa:reference>
在 Annotation 中配置
使用 Annotation 方式發布 JVM 服務和引用時,可以通過設置 @SofaService
和 @SofaReference
的 uniqueId 屬性來設置 uniqueId。
在編程 API 中配置
使用編程 API 方式發布或者引用 JVM 服務時,可以通過 ServiceParam
和 ReferenceParam
的 setUniqueId 方法來設置 uniqueId。