完整源码:java
应用场景描述:git
服务提供者在项目启动时,建立并启动一个TCP服务器,而后将本身提供的全部服务注册到注册中心。
这里有3个角色:服务器
1.服务提供者
2.TCP服务器
3.注册中心
引出回调:tcp
服务提供者,要求TCP服务器启动成功以后,回调一下"注册服务"的逻辑。
开始撸码:ide
首先定义一个回调基类,这是一个抽象类,里面只有一个抽象的回调函数,是未来回调时要实现的方法函数
1 /**
2 * 回调基类3 *4 *@authorsyj5 */
6 public abstract classBaseCallBack {7 /**
8 * 回调执行逻辑9 *10 *@throwsException11 */
12 public abstract void run() throwsException;13 }
谁来调用这个回调函数呢,前面说了,TCP服务器启动以后要调用这个回调函数,因此回调的操做要在TCP服务器中完成。测试
TCP服务器是一个具体的服务实现,咱们可能会有多种服务器的实现,因此先定义一个抽象的服务类:this
1 /**
2 * 服务抽象3 *4 *@authorsyj5 */
6 public abstract classServer {7
8 //服务启动后回调
9 privateBaseCallBack startedCallBack;10
11 //服务中止后回调
12 privateBaseCallBack stopedCallBack;13
14 /**
15 * 设置服务启动后的回调逻辑16 *17 *@paramstartedCallBack18 */
19 public voidsetStartedCallBack(BaseCallBack startedCallBack) {20 this.startedCallBack =startedCallBack;21 }22
23 /**
24 * 设置服务中止后的回调逻辑25 *26 *@paramstopedCallBack27 */
28 public voidsetStopedCallBack(BaseCallBack stopedCallBack) {29 this.stopedCallBack =stopedCallBack;30 }31
32 /**
33 * 服务启动后回调34 */
35 public voidonStarted() {36 if (startedCallBack != null) {37 try{38 startedCallBack.run();39 } catch(Exception e) {40 e.printStackTrace();41 }42 }43 }44
45 /**
46 * 服务中止后回调47 */
48 public voidonStoped() {49 if (stopedCallBack != null) {50 try{51 stopedCallBack.run();52 } catch(Exception e) {53 e.printStackTrace();54 }55 }56 }57
58 /**
59 * 启动服务60 *61 *@paramprovider62 *@throwsException63 */
64 public abstract void start(Provider provider) throwsException;65
66 /**
67 * 中止服务68 *69 *@throwsException70 */
71 public abstract void stop() throwsException;72
73 }
这个服务器抽象类,主要有启动服务和中止服务的方法,还持有两个回调对象,一个是服务器启动后的回调对象,一个是服务器中止后的回调对象。并有两个方法分别去调用这两个回调对象的run方法。spa
下面定义一个TCP服务器类,它是上面服务器抽象类的一个具体实现类:code
1 /**
2 * 服务实现类3 *4 *@authorsyj5 */
6 public class TcpServerImpl extendsServer {7
8
9 /**
10 * 启动服务11 *12 *@paramprovider13 */
14 @Override15 public voidstart(Provider provider) {16 System.out.println(">>>> start! " + provider.getTcpSrvAddr() + ":" +provider.getTcpSrvPort());17 //启动后回调
18 onStarted();19
20 }21
22 /**
23 * 中止服务24 *25 */
26 @Override27 public voidstop() {28 System.out.println(">>>> stop!");29 //中止后回调
30 onStoped();31 }32 }
该类主要有两个功能,一个是启动TCP服务,一个是中止TCP服务,这两个方法的最后都须要触发回调逻辑的执行;
关于具体回调逻辑的定义写在哪里呢?天然是服务的提供者最清楚,因此写在服务提供者类中最合适:
1 importjava.util.TreeSet;2
3 /**
4 * 服务操做5 *6 *@authorsyj7 */
8 public classProvider {9
10 //模拟要注册的服务列表
11 public static TreeSet serviceKeys = new TreeSet() {{12 add("userService");13 add("productService");14 add("orderService");15 }};16
17 //模拟本机http服务使用的ip和端口
18 public static String localAddress = "127.0.0.1:8081";19
20 //TCP服务器地址
21 privateString tcpSrvAddr;22
23 //TCP服务器端口
24 private inttcpSrvPort;25
26 publicString getTcpSrvAddr() {27 returntcpSrvAddr;28 }29
30 public intgetTcpSrvPort() {31 returntcpSrvPort;32 }33
34 privateServer server;35 privateRegistry registry;36
37 publicProvider() {38 }39
40 /**
41 * 初始化配置42 *43 *@paramtcpSrvAddr44 *@paramtcpSrvPort45 */
46 public void initConfig(String tcpSrvAddr, inttcpSrvPort) {47 this.tcpSrvAddr =tcpSrvAddr;48 this.tcpSrvPort =tcpSrvPort;49 }50
51 /**
52 * 启动服务53 */
54 public voidstart() {55 try{56 registry = Registry.class.newInstance();57 server = TcpServerImpl.class.newInstance();58 //设置服务启动后回调逻辑
59 server.setStartedCallBack(newBaseCallBack() {60 @Override61 public voidrun() {62 System.out.println(">>>> setStartedCallBack:" + serviceKeys + ":" +localAddress);63 //注册服务
64 registry.start();65 registry.registry(serviceKeys, localAddress);66 }67 });68
69 //设置服务中止后回调逻辑
70 server.setStopedCallBack(newBaseCallBack() {71 @Override72 public voidrun() {73 System.out.println(">>>> setStopedCallBack:" + tcpSrvAddr + ":" +tcpSrvPort);74 registry.remove(serviceKeys, localAddress);75 }76 });77
78 //启动服务
79 server.start(this);80 } catch(Exception e) {81 e.printStackTrace();82 }83 }84
85 /**
86 * 中止服务87 */
88 public voidstop() {89 try{90 server.stop();91 } catch(Exception e) {92 e.printStackTrace();93 }94 }95 }
因为服务提供者须要启动TCP服务器,因此它依赖一个Server对象,在他的start方法中,启动TCP服务以前,先给这个TCP服务设置两个回调回调具体逻辑,就是前面说的一个是TCP服务器启动以后要执行的逻辑,一个是TCP服务器中止以后要执行的逻辑。
TCP服务器启动成功以后,要将服务提供者的全部服务注册到注册中心,TCP服务器中止以后要从注册中心移除本身的全部服务。
下面是注册中心类,它只负责服务的注册和移除,别的事无论:
1 importjava.util.HashMap;2 importjava.util.Map;3 importjava.util.Set;4 importjava.util.TreeSet;5
6 /**
7 * 服务注册中心8 *9 *@authorsyj10 */
11 public classRegistry {12
13 private Map>registryData;14
15
16 public voidstart() {17 registryData = new HashMap>();18 System.out.println(">>>> 注册中心建立成功");19 }20
21 public voidstop() {22 registryData.clear();23 }24
25
26 public boolean registry(Setkeys, String value) {27 if (keys==null || keys.size()==0 || value==null || value.trim().length()==0) {28 return false;29 }30 for(String key : keys) {31 TreeSet values =registryData.get(key);32 if (values == null) {33 values = new TreeSet<>();34 registryData.put(key, values);35 }36 values.add(value);37 }38 System.out.println(">>>> 服务注册成功");39 return true;40 }41
42 public boolean remove(Setkeys, String value) {43 if (keys==null || keys.size()==0 || value==null || value.trim().length()==0) {44 return false;45 }46 for(String key : keys) {47 TreeSet values =registryData.get(key);48 if (values != null) {49 values.remove(value);50 }51 }52 System.out.println(">>>> 服务移除成功");53 return true;54 }55 }
写个测试类测试一下:
1 /**
2 * 测试类3 *4 *@authorsyj5 */
6 public classApp {7 //TCP 服务器IP
8 public static String tcpSrvAddr = "192.168.11.23";9 //TCP 服务端口
10 public static int tcpSrvPort = 9090;11
12 public static voidmain(String[] args) {13 Provider provider = newProvider();14 provider.initConfig(tcpSrvAddr, tcpSrvPort);15 provider.start();16 provider.stop();17 }18 }
输出结果:
>>>> start! 192.168.11.23:9090
>>>> setStartedCallBack:[orderService, productService, userService]:127.0.0.1:8081
>>>>注册中心建立成功>>>>服务注册成功>>>> stop!
>>>> setStopedCallBack:192.168.11.23:9090
>>>> 服务移除成功
总结:
A类调用B类的某个方法,B类的该方法中又调用了A类的某个方法,这就是回调。
这仅是一个形象的描述,具体的回调机制在实际应用时会很灵活。
好比这个例子中,Provider类的start方法调用啦Server类的start方法,而Server类的start方法中又调用了onStarted方法,
虽然这个onStarted方法不是Provider中的方法,但其执行的回调逻辑是在Provider中经过setStartedCallBack()来设置的。