(7)SOFARPC 注解支持剖析(沒找到對應(yīng)代碼)

SOFARPC 發(fā)布引用 RPC 服務(wù)方式:

1、XML 方式(配置):xml引入 SOFA 命名空間,Bean 生命周期管理, Bean 的注入

2、Annotation 方式(注解):發(fā)布 JVM 服務(wù)更靈活,實(shí)現(xiàn)類上加?@SofaService、@SofaRefernce

3、編程 API 方式(動態(tài)):與Spring 的?ApplicationContextAware?類似

一、注解原理解析

1.1、注解是什么

元數(shù)據(jù),形式化對代碼中添加信息,編譯、運(yùn)行時使用。繼承 Annotation 接口的接口。有解析它代碼特殊注釋,常用:

(1)Java自帶:@Override、@Deprecated(過時)、@SuppressWarnings;

(2)元注解:定義注解的注解;(3)自定義注解

1.2、元注解(JAVA 元注解)

1、@Target:指明修飾方法、類、字段屬性:

ElementType.TYPE:允許被修飾的注解作用在類、接口和枚舉

????ElementType.FIELD:作用屬性字段上

????ElementType.METHOD:作用方法上

????ElementType.PARAMETER:方法參數(shù)

????ElementType.CONSTRUCTOR:構(gòu)造器

????ElementType.LOCAL_VARIABLE:本地局部變量

????ElementType.ANNOTATION_TYPE:注解

????ElementType.PACKAGE:允許作用在包上

2、@Retention:被修飾注解的生命周期,三種類型:

RetentionPolicy.SOURCE:只保留源文件中,編譯成class時,class中木有。

RetentionPolicy.CLASS:只保留class文件中,加載class文件內(nèi)存,虛擬機(jī)將注解去掉,程序中不能訪問。

RetentionPolicy.RUNTIME:運(yùn)行期內(nèi)存中。反射獲得某個類上所有注解。

3、@Documented:執(zhí)行 JavaDoc 文檔打包被保存 doc 文檔,反之打包時丟棄。

4、@Inherited:可繼承性,修飾類的子類自動繼承父類的該注解。

1.3、注解解析方式

1.3.1、編譯器的掃描

指的是編譯器在對 java 代碼編譯字節(jié)碼的過程中會檢測到某個類或者方法被一些注解修飾,這時它就會對于這些注解進(jìn)行某些處理。典型的就是注解?@Override,一旦編譯器檢測到某個方法被修飾了?@Override?注解,編譯器就會檢查當(dāng)前方法的方法簽名是否真正重寫了父類的某個方法,也就是比較父類中是否具有一個同樣的方法簽名。

這一種情況只適用于那些編譯器已經(jīng)熟知的注解類,比如 JDK 內(nèi)置的幾個注解,而你自定義的注解,編譯器是不知道你這個注解的作用的。

1.3.1、運(yùn)行期反射

首先對虛擬機(jī)的幾個注解相關(guān)的屬性表進(jìn)行介紹,先大體了解注解在字節(jié)碼文件中是如何存儲的。虛擬機(jī)規(guī)范定義了一系列和注解相關(guān)的屬性表,也就是說,無論是字段、方法或是類本身,如果被注解修飾了,就可以被寫進(jìn)字節(jié)碼文件。屬性表有以下幾種:

RuntimeVisibleAnnotations:運(yùn)行時可見的注解

RuntimeInVisibleAnnotations:運(yùn)行時不可見的注解

RuntimeVisibleParameterAnnotations:運(yùn)行時可見的方法參數(shù)注解

RuntimeInVisibleParameterAnnotations:運(yùn)行時不可見的方法參數(shù)注解

AnnotationDefault:注解類元素的默認(rèn)值

java.lang.reflect.AnnotatedElement接口是所有程序元素(Class、Method和Constructor)的父接口,程序通過反射獲取了某個類的 AnnotatedElemen t對象之后,利用 Java 的反射機(jī)獲取程序代碼中的注解,然后根據(jù)預(yù)先設(shè)定的處理規(guī)則解析處理相關(guān)注解以達(dá)到主機(jī)本身設(shè)定的功能目標(biāo)。

本質(zhì)上來說,反射機(jī)制就是注解使用的核心,程序可以調(diào)用該對象的以下方法來訪問 Annotation信息:

getAnnotation:返回指定的注解

isAnnotationPresent:判定當(dāng)前元素是否被指定注解修飾

getAnnotations:返回所有的注解

getDeclaredAnnotation:返回本元素的指定注解

getDeclaredAnnotations:返回本元素的所有注解,不包含父類繼承而來的

二、SOFARPC 源碼解析

2.1、注解說明

以com.alipay.sofa.runtime.api.annotation.SofaReference?為例子(SofaService 類似),源碼如下:

@SofaReference?生命周期為 RetentionPolicy.RUNTIME,永久保存,反射獲取;

注解作用目標(biāo) ElementType.FIELD,ElementType.METHOD,允許作用在方法和屬性字段上;

RPC 綁定方式 JVM、BOLT、REST 三種;默認(rèn)服務(wù)綁定關(guān)系為 JVM 方式;

2.2、服務(wù)發(fā)布與引用解析

通過?ServiceAnnotationBeanPostProcesso?類中postProcessAfterInitialization、postProcessBeforeInitialization 分別進(jìn)行服務(wù)的發(fā)布和引用:

獲取 SofaService.class、SofaReference.class 指定注解

獲取 SOFA 引用類型,默認(rèn) void,獲取引用uniqueId

2.2.1、總體流程

服務(wù)發(fā)布和引用整體流程圖,主要包含:注解解析、組件生成、組件注冊。

2.2.2、服務(wù)發(fā)布

目標(biāo):@SofaService類注冊SOFA Context 中。發(fā)布到 SofaRuntimeContext 的過程其實(shí)就是把服務(wù)組件對象塞到?ConcurrentMap<ComponentName, ComponentInfo> registry對象中,通過 registry 進(jìn)行查找。

步驟:

(1)遍歷 SOFA 綁定關(guān)系, handleSofaServiceBinding 方法進(jìn)行不同類型 RPC Binding。

(2)生成 ServiceComponent 服務(wù)組件。

(3)調(diào)用 ServiceComponent 的register、resolve、activate方法,逐一調(diào)用對應(yīng) BindingAdapter 對外暴露服務(wù)。

(4)不同 BindingAdapter的 outBinding 服務(wù)處理策略不同。JvmBindingAdapter 返回空,不需暴露給外部,直接通過 registry 對象查找來調(diào)用;?RPC BindingAdapter 將服務(wù)信息推送注冊中心 Config。

將 ServiceComponent 注冊到 sofa 的上下文sofaRuntimeContext 中。

2.2.3、服務(wù)引用

目標(biāo):@SofaReference將 SOFA Context 中服務(wù)注冊成 Spring 中bean。通過?ReferenceRegisterHelper.registerReference()?方法從上下文中g(shù)et代理對象,?

registerReference() 內(nèi)部操作:

(1)注解 jvmFirst()?為 true 時,自動添加本地 JVM binding,避免跨機(jī)調(diào)用。

(2)生成 ReferenceComponent 服務(wù)組件對象。

(3)與 ServiceComponent 處理方式類似,ReferenceComponent 也會添加到ConcurrentMap<ComponentName, ComponentInfo> registry對象中,分別執(zhí)行組件的register、resolve、activate 三個方法。其中 register、resolve 方法主要是改變組件生命周期代理對象生成就是在 activate 方法中完成。

(4)ReferenceComponent 組件通過不同類型 binding 生成不同類型的代理對象。只有一個binding,使用當(dāng)前;多個 binding,優(yōu)先用 jvm binding 來生成本地調(diào)用的代理對象,本地不存在,用遠(yuǎn)程代理對象。

(5)JvmBindingAdapterinBinding 方法,直接借助于動態(tài)代理技術(shù)進(jìn)行生成代理對象,對于 RpcBindingAdapter 的 inBinding,在構(gòu)造的過程存在向注冊中心訂閱的邏輯。

?4、總結(jié)

1、XML :配置簡潔,但編碼多

Annotation:@SofaService 省去<sofa:service>?聲明,bean 定義必須有

SOFA: 注冊BeanPostProcessor處理@SofaService?和?@SofaReference注解。發(fā)布引用對象屬于當(dāng)前 bean 實(shí)例變量, xml 方式發(fā)布和引用, Bean 生命周期 InitializingBean#afterPropertiesSet?方法進(jìn)行擴(kuò)展。工程中注解掃描是對所有 bean 操作,只能通過實(shí)現(xiàn) spring 的 beanpostprocessor 這個接口,另外有些屬性可能在發(fā)布時需要用到。

注解服務(wù)發(fā)布和引用,分別基于 Bean 生命周期 BeanPostProcessor#postProcessAfterInitialization、#postProcessBeforeInitialization方法擴(kuò)展。

發(fā)布引用方式:

? ??XML:集中式元數(shù)據(jù),不綁源代碼

? ??注解:分散式的元數(shù)據(jù),綁定源代碼。

參考文檔

Java annotation:

https://en.wikipedia.org/wiki/Java_annotation

SOFASTACK 服務(wù)發(fā)布/服務(wù)引用:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容