### Question:
ZookeeperDynamicConfiguration implements DynamicConfiguration { @Override public void addListener(String key, String group, ConfigurationListener listener) { cacheListener.addListener(key, listener); } ZookeeperDynamicConfiguration(URL url); @Override Object getInternalProperty(String key); @Override void addListener(String key, String group, ConfigurationListener listener); @Override void removeListener(String key, String group, ConfigurationListener listener); @Override String getConfig(String key, String group, long timeout);  }### Answer:
@Test public void testAddListener() throws Exception { CountDownLatch latch = new CountDownLatch(4); TestListener listener1 = new TestListener(latch); TestListener listener2 = new TestListener(latch); TestListener listener3 = new TestListener(latch); TestListener listener4 = new TestListener(latch); configuration.addListener("group*service:version.configurators", listener1); configuration.addListener("group*service:version.configurators", listener2); configuration.addListener("appname.tagrouters", listener3); configuration.addListener("appname.tagrouters", listener4); setData("/dubbo/config/group*service:version/configurators", "new value1"); Thread.sleep(100); setData("/dubbo/config/appname/tagrouters", "new value2"); Thread.sleep(100); setData("/dubbo/config/appname", "new value3"); Thread.sleep(5000); latch.await(); Assertions.assertEquals(1, listener1.getCount("group*service:version.configurators")); Assertions.assertEquals(1, listener2.getCount("group*service:version.configurators")); Assertions.assertEquals(1, listener3.getCount("appname.tagrouters")); Assertions.assertEquals(1, listener4.getCount("appname.tagrouters")); Assertions.assertEquals("new value1", listener1.getValue()); Assertions.assertEquals("new value1", listener2.getValue()); Assertions.assertEquals("new value2", listener3.getValue()); Assertions.assertEquals("new value2", listener4.getValue()); }