diff --git a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManager.java b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManager.java index 36acb3ad349..5e0764eb3b6 100644 --- a/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManager.java +++ b/client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManager.java @@ -36,12 +36,27 @@ public class ConfigFilterChainManager implements IConfigFilterChain { private final List filters = new ArrayList<>(); + private IConfigFilterChain filterChain; + public ConfigFilterChainManager(Properties properties) { ServiceLoader configFilters = ServiceLoader.load(IConfigFilter.class); for (IConfigFilter configFilter : configFilters) { configFilter.init(properties); addFilter(configFilter); } + buildConfigFilterChain(); + } + + /** + * Build ConfigFilterChain. + */ + public void buildConfigFilterChain() { + filterChain = new EmptyFilterChainNode(); + for (int i = filters.size() - 1; i >= 0; i--) { + final IConfigFilter filter = filters.get(i); + final IConfigFilterChain next = filterChain; + filterChain = new FilterChainNode(filter, next); + } } /** @@ -74,26 +89,31 @@ public synchronized ConfigFilterChainManager addFilter(IConfigFilter filter) { @Override public void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException { - new VirtualFilterChain(this.filters).doFilter(request, response); + filterChain.doFilter(request, response); } - private static class VirtualFilterChain implements IConfigFilterChain { + private static class FilterChainNode implements IConfigFilterChain { - private final List additionalFilters; + private final IConfigFilter filter; - private int currentPosition = 0; + private final IConfigFilterChain next; - public VirtualFilterChain(List additionalFilters) { - this.additionalFilters = additionalFilters; + public FilterChainNode(IConfigFilter filter, IConfigFilterChain next) { + this.filter = filter; + this.next = next; } @Override - public void doFilter(final IConfigRequest request, final IConfigResponse response) throws NacosException { - if (this.currentPosition != this.additionalFilters.size()) { - this.currentPosition++; - IConfigFilter nextFilter = this.additionalFilters.get(this.currentPosition - 1); - nextFilter.doFilter(request, response, this); - } + public void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException { + filter.doFilter(request, response, next); + } + } + + private static class EmptyFilterChainNode implements IConfigFilterChain { + + @Override + public void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException { + } } diff --git a/client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManagerTest.java b/client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManagerTest.java index 1d62d243777..f041250eb41 100644 --- a/client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManagerTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManagerTest.java @@ -43,11 +43,11 @@ public MyIConfigFilter(String name, int order) { this.name = name; this.order = order; } - + @Override public void init(IFilterConfig filterConfig) { } - + @Override public void init(Properties properties) { } @@ -100,6 +100,7 @@ public void testAddFilterOrder() throws NacosException { configFilterChainManager.addFilter(filter2); configFilterChainManager.addFilter(filter1); configFilterChainManager.addFilter(filter3); + configFilterChainManager.buildConfigFilterChain(); ConfigRequest configRequest = new ConfigRequest(); @@ -127,6 +128,7 @@ public void testAddFilterNotRepeat() throws NacosException { configFilterChainManager.addFilter(filter2); configFilterChainManager.addFilter(filter1); configFilterChainManager.addFilter(repeatFilter); + configFilterChainManager.buildConfigFilterChain(); ConfigRequest configRequest = new ConfigRequest(); configFilterChainManager.doFilter(configRequest, new ConfigResponse()); @@ -135,4 +137,28 @@ public void testAddFilterNotRepeat() throws NacosException { Assert.assertEquals(2, configContext.getParameter("filterCount")); } + + @Test + public void testSpiFilterNodeChain() throws NacosException { + final ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager(new Properties()); + + configFilterChainManager.doFilter(new ConfigRequest(), new ConfigResponse()); + } + + @Test + public void testAddFilterNodeChain() throws NacosException { + final ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager(new Properties()); + + MyIConfigFilter filter1 = new MyIConfigFilter("filter1", 1); + MyIConfigFilter filter2 = new MyIConfigFilter("filter2", 2); + MyIConfigFilter filter3 = new MyIConfigFilter("filter3", 3); + + configFilterChainManager.addFilter(filter2); + configFilterChainManager.addFilter(filter1); + configFilterChainManager.addFilter(filter3); + // When an external filter is added via the addFilter() method, the responsibility chain only needs to be rebuilt, which in fact is rare. + configFilterChainManager.buildConfigFilterChain(); + + configFilterChainManager.doFilter(new ConfigRequest(), new ConfigResponse()); + } } \ No newline at end of file diff --git a/client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainTest.java b/client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainTest.java index 379bd1af051..d029c0e91fc 100644 --- a/client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainTest.java +++ b/client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainTest.java @@ -27,6 +27,8 @@ public void testConfigFilterChain() { ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager(null); configFilterChainManager.addFilter(new DemoFilter1()); configFilterChainManager.addFilter(new DemoFilter2()); + configFilterChainManager.buildConfigFilterChain(); + ConfigRequest configRequest = new ConfigRequest(); ConfigResponse configResponse = new ConfigResponse(); try {