如果使用傳統(tǒng)的方式來(lái)進(jìn)行通信的話(huà),那么服務(wù)啟動(dòng)端需要先手動(dòng)創(chuàng)建一個(gè)提供服務(wù)的類(lèi)的實(shí)例
HelloService helloService = new HelloServiceImpl();
雖然在實(shí)現(xiàn)過(guò)程中只有這一個(gè)服務(wù),好像并不會(huì)帶來(lái)太大的問(wèn)題,但如果有一堆服務(wù)對(duì)象的話(huà),那有幾個(gè)就得手動(dòng)創(chuàng)建幾個(gè),這樣肯定是不現(xiàn)實(shí)的,所以給框架加一個(gè)自動(dòng)注冊(cè)服務(wù)的方式是很有必要的。采用注解的方式來(lái)解決這個(gè)問(wèn)題則是個(gè)很好的選擇。
服務(wù)端肯定要有一個(gè)注解,當(dāng)我們啟動(dòng)服務(wù)端后,原本是創(chuàng)建一個(gè)服務(wù)類(lèi)的實(shí)例,需要將這一步省去,這個(gè)注解可以視為掃描注解,實(shí)現(xiàn)了這個(gè)注解之后,我們就知道了在這個(gè)位置需要進(jìn)行掃描。同時(shí),提供服務(wù)的類(lèi)也可以有一個(gè)注解,表明它提供了一個(gè)服務(wù)。
我們就可以設(shè)計(jì)如下的流程:獲取服務(wù)啟動(dòng)端所在的類(lèi)名→判斷該類(lèi)下有無(wú)掃描注解→獲取注解的值如果值與我們定義的相同,說(shuō)明是我們需要操作的類(lèi)→獲取它所在的包的名稱(chēng)→掃描包下所有類(lèi),逐個(gè)判斷是否有服務(wù)注解→獲取注解類(lèi)實(shí)現(xiàn)的接口→得到接口信息,注冊(cè)服務(wù)
//服務(wù)注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
public String name() default "";
}
//掃描注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceScan {
public String value() default "";
}
服務(wù)端
@ServiceScan
public class NettyServerTest {
public static void main(String[] args) {
NettyServer server = new NettyServer("127.0.0.1", 9999, CommonSerializer.KRYO_SERIALIZER);
server.start();
}
}
這又會(huì)出現(xiàn)一個(gè)問(wèn)題,我們知道在服務(wù)端啟動(dòng)時(shí)需要進(jìn)行掃描,但是怎么獲得這個(gè)服務(wù)端的類(lèi)名呢?
我們是通過(guò)調(diào)用main方法來(lái)啟動(dòng)服務(wù)的,當(dāng)一個(gè)方法被調(diào)用時(shí),實(shí)際上是線(xiàn)程調(diào)用了它私有的虛擬機(jī)棧,將方法作為一個(gè)棧幀將其壓入虛擬機(jī)棧中,一個(gè)方法從開(kāi)始執(zhí)行到執(zhí)行完畢對(duì)應(yīng)的就是它的入棧和出棧過(guò)程,所以main方法肯定是在棧底的,我們可以通過(guò)new Throwable().getStackTrace()方法得到棧幀信息。
getStackTrace()返回一個(gè)表示該線(xiàn)程堆棧轉(zhuǎn)儲(chǔ)的堆棧跟蹤元素?cái)?shù)組。如果該線(xiàn)程尚未啟動(dòng)或已經(jīng)終止,則該方法將返回一個(gè)零長(zhǎng)度數(shù)組。如果返回的數(shù)組不是零長(zhǎng)度的,則其第一個(gè)元素代表堆棧頂,它是該序列中最新的方法調(diào)用。最后一個(gè)元素代表堆棧底,是該序列中最舊的方法調(diào)用。
public static String getStackTrace() {
StackTraceElement[] stack = new Throwable().getStackTrace();
return stack[stack.length - 1].getClassName();
}
有了基本思路以后,實(shí)現(xiàn)起來(lái)就沒(méi)那么困難了