This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
commit a5834cbc56bae9e3c0c4086138d45e7a87c22fa3 Author: wujimin <[email protected]> AuthorDate: Thu Nov 22 22:35:11 2018 +0800 [SCB-1034] replace guava EventBus by simple version --- .../foundation/common/event/EventBus.java | 79 ------------------- .../foundation/common/event/EventListener.java | 26 ------ .../foundation/common/event/EventManager.java | 2 +- .../foundation/common/event/SimpleEventBus.java | 92 ++++++++++++++++++++++ .../foundation/common/event/SimpleSubscriber.java | 85 ++++++++++++++++++++ .../foundation/common/event/TestEventBus.java | 84 -------------------- .../foundation/common/event/TestEventManager.java | 66 +++++++++++++--- .../consumer/RSAConsumerTokenManager.java | 4 +- java-chassis-dependencies/pom.xml | 2 +- java-chassis-distribution/src/release/LICENSE | 2 +- ...rvicecomb.foundation.common.event.EventListener | 37 --------- 11 files changed, 235 insertions(+), 244 deletions(-) diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java deleted file mode 100644 index 849089a..0000000 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventBus.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.servicecomb.foundation.common.event; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class EventBus { - private static final Logger LOGGER = LoggerFactory.getLogger(EventBus.class); - - //key is event object type,fast locate listener and fire - @SuppressWarnings("rawtypes") - private final Map<Class, List<EventListener>> allEventListeners = new ConcurrentHashMapEx<>(); - - private static final EventBus INSTANCE = new EventBus(); - - public static EventBus getInstance() { - return INSTANCE; - } - - //event class will get from getEventClass method - @SuppressWarnings({"rawtypes"}) - private EventBus() { - List<EventListener> listeners = SPIServiceUtils.getAllService(EventListener.class); - for (EventListener listener : listeners) { - this.registerEventListener(listener); - LOGGER.info("EventBus register " + listener.getClass().getName() - + " for process " + listener.getEventClass().getName()); - } - } - - //event class will get from getEventClass method - @SuppressWarnings("rawtypes") - public void registerEventListener(EventListener eventListener) { - List<EventListener> eventListeners = allEventListeners - .computeIfAbsent(eventListener.getEventClass(), f -> new CopyOnWriteArrayList<>()); - eventListeners.add(eventListener); - } - - //event class will get from getEventClass method - @SuppressWarnings("rawtypes") - public void unregisterEventListener(EventListener eventListener) { - List<EventListener> eventListeners = allEventListeners - .computeIfAbsent(eventListener.getEventClass(), f -> new CopyOnWriteArrayList<>()); - if (eventListeners.contains(eventListener)) { - eventListeners.remove(eventListener); - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - public void triggerEvent(Object event) { - List<EventListener> eventListeners = allEventListeners.getOrDefault(event.getClass(), Collections.emptyList()); - for (EventListener eventListener : eventListeners) { - eventListener.process(event); - } - } -} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventListener.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventListener.java deleted file mode 100644 index 7924e1d..0000000 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventListener.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.servicecomb.foundation.common.event; - -//Common event listener interface,java chassis component can trigger event let high level component perceive data change. -public interface EventListener<T> { - Class<T> getEventClass(); - - //process event data - void process(T data); -} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java index cb72a21..6e59293 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java @@ -24,7 +24,7 @@ import com.google.common.eventbus.EventBus; * */ public class EventManager { - public static EventBus eventBus = new EventBus(); + public static EventBus eventBus = new SimpleEventBus(); public static EventBus getEventBus() { return eventBus; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleEventBus.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleEventBus.java new file mode 100644 index 0000000..1dfbd97 --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleEventBus.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.servicecomb.foundation.common.event; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.reflect.MethodUtils; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + +/** + * for register/unregister rarely + */ +public class SimpleEventBus extends EventBus { + private final Map<Object, List<SimpleSubscriber>> subscribersMap = new ConcurrentHashMapEx<>(); + + // key is event class + private Map<Class<?>, List<SimpleSubscriber>> subscribersCache = new ConcurrentHashMapEx<>(); + + private List<SimpleSubscriber> collectSubscribers(Object instance) { + List<SimpleSubscriber> subscribers = new ArrayList<>(); + Method[] methods = MethodUtils.getMethodsWithAnnotation(instance.getClass(), Subscribe.class, true, true); + for (Method method : methods) { + SimpleSubscriber subscriber = new SimpleSubscriber(instance, method); + subscribers.add(subscriber); + } + return subscribers; + } + + @Override + public void register(Object instance) { + subscribersMap.computeIfAbsent(instance, this::collectSubscribers); + // even ignored cause of duplicate register + // still reset cache + // this makes logic simpler + subscribersCache = new ConcurrentHashMapEx<>(); + } + + @Override + public void unregister(Object instance) { + if (subscribersMap.remove(instance) != null) { + subscribersCache = new ConcurrentHashMapEx<>(); + } + } + + public void post(Object event) { + // cache always reset after register/unregister + // so cache always match latest subscribersMap at last + // te worst scenes is invoke collectSubscriberForEvent multiple times, no problem + List<SimpleSubscriber> subscribers = subscribersCache + .computeIfAbsent(event.getClass(), this::collectSubscriberForEvent); + for (SimpleSubscriber subscriber : subscribers) { + subscriber.dispatchEvent(event); + } + } + + /** + * subscribersMap almost stable<br> + * so we not care for performance of collectSubscriberForEvent + * @param eventClass + */ + private List<SimpleSubscriber> collectSubscriberForEvent(Class<?> eventClass) { + List<SimpleSubscriber> subscribersForEvent = new ArrayList<>(); + for (List<SimpleSubscriber> subscribers : subscribersMap.values()) { + for (SimpleSubscriber subscriber : subscribers) { + if (subscriber.getMethod().getParameterTypes()[0].isAssignableFrom(eventClass)) { + subscribersForEvent.add(subscriber); + } + } + } + return subscribersForEvent; + } +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java new file mode 100644 index 0000000..e83a6bd --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.servicecomb.foundation.common.event; + +import java.lang.reflect.Method; +import java.util.function.Consumer; + +import org.apache.servicecomb.foundation.common.utils.LambdaMetafactoryUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.eventbus.AllowConcurrentEvents; + +public class SimpleSubscriber { + private static final Logger LOGGER = LoggerFactory.getLogger(SimpleSubscriber.class); + + private Object instance; + + private Method method; + + // generated from method + private Consumer<Object> lambda; + + private Consumer<Object> dispatcher; + + public SimpleSubscriber(Object instance, Method method) { + this.instance = instance; + this.method = method; + + method.setAccessible(true); + try { + lambda = LambdaMetafactoryUtils.createLambda(instance, method, Consumer.class); + } catch (Throwable throwable) { + LOGGER.warn("Failed to create lambda for method: {}, fallback to reflect.", method); + lambda = event -> { + try { + method.invoke(instance, event); + } catch (Throwable e) { + throw new IllegalStateException(e); + } + }; + } + + dispatcher = this::syncDispatch; + if (method.getAnnotation(AllowConcurrentEvents.class) != null) { + dispatcher = this::concurrentDispatch; + } + } + + public Object getInstance() { + return instance; + } + + public Method getMethod() { + return method; + } + + public void dispatchEvent(Object event) { + dispatcher.accept(event); + } + + private void syncDispatch(Object event) { + synchronized (this) { + lambda.accept(event); + } + } + + private void concurrentDispatch(Object event) { + lambda.accept(event); + } +} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java deleted file mode 100644 index 77264ad..0000000 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.servicecomb.foundation.common.event; - -import static org.awaitility.Awaitility.await; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class TestEventBus { - - private AtomicBoolean eventReceived = new AtomicBoolean(false); - - private EventListener<String> listener = new EventListener<String>() { - @Override - public Class<String> getEventClass() { - return String.class; - } - - @Override - public void process(String data) { - eventReceived.set(true); - } - }; - - @Before - public void reset() { - EventBus.getInstance().unregisterEventListener(listener); - } - - @Test - public void checkEventReceivedAndProcessed() { - EventBus.getInstance().registerEventListener(listener); - - EventBus.getInstance().triggerEvent("xxx"); - await().atMost(1, TimeUnit.SECONDS) - .until(eventReceived::get); - Assert.assertTrue(eventReceived.get()); - } - - @Test - public void checkEventCanNotReceivedAfterUnregister() { - EventBus.getInstance().registerEventListener(listener); - - EventBus.getInstance().triggerEvent("xxx"); - await().atMost(1, TimeUnit.SECONDS) - .until(eventReceived::get); - Assert.assertTrue(eventReceived.get()); - - eventReceived.set(false); - - EventBus.getInstance().unregisterEventListener(listener); - EventBus.getInstance().triggerEvent("xxx"); - Assert.assertFalse(eventReceived.get()); - } - - @Test - public void checkUnmatchTypeWillNotReceived() { - EventBus.getInstance().registerEventListener(listener); - - //trigger a Integer type event object - EventBus.getInstance().triggerEvent(1); - Assert.assertFalse(eventReceived.get()); - } -} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java index 192d97c..6073a41 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java @@ -17,34 +17,74 @@ package org.apache.servicecomb.foundation.common.event; +import java.util.stream.Collectors; + +import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; +import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; import com.google.common.eventbus.Subscribe; public class TestEventManager { + private int objCount = 0; + + private int iCount = 0; - private int i = 0; + public void test(Object listener) { + EventManager.register(listener); + EventManager.post("a"); + EventManager.post(1); + Assert.assertEquals(2, objCount); + Assert.assertEquals(1, iCount); + + EventManager.unregister(listener); + EventManager.post("a"); + EventManager.post(1); + Assert.assertEquals(2, objCount); + Assert.assertEquals(1, iCount); + } @Test - public void testRegister() { - EventManager.register(this); - EventManager.post(this); - EventManager.unregister(this); - Assert.assertEquals(1, i); + public void lambda() { + LogCollector collector = new LogCollector(); + + test(this); + Assert.assertTrue(collector.getEvents().isEmpty()); + collector.teardown(); } @Test - public void testUnregister() { - EventManager.register(this); - EventManager.unregister(this); - EventManager.post(this); - Assert.assertEquals(0, i); + public void reflect() { + LogCollector collector = new LogCollector(); + Object listener = new Object() { + @Subscribe + public void onObject(Object obj) { + objCount++; + } + + @Subscribe + public void onInt(Integer obj) { + iCount++; + } + }; + test(listener); + Assert.assertThat(collector.getEvents().stream().map(e -> e.getMessage()).collect(Collectors.toList()), + Matchers.containsInAnyOrder( + "Failed to create lambda for method: public void org.apache.servicecomb.foundation.common.event.TestEventManager$1.onObject(java.lang.Object), fallback to reflect.", + "Failed to create lambda for method: public void org.apache.servicecomb.foundation.common.event.TestEventManager$1.onInt(java.lang.Integer), fallback to reflect.")); + + collector.teardown(); + } + + @Subscribe + public void onObject(Object obj) { + objCount++; } @Subscribe - public void eventCallBack(TestEventManager lTestEventManager) { - i++; + public void onInt(Integer obj) { + iCount++; } } diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java index 6679415..d3c610c 100644 --- a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java @@ -22,7 +22,6 @@ import java.security.PrivateKey; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; -import org.apache.commons.lang3.RandomStringUtils; import org.apache.servicecomb.authentication.RSAAuthenticationToken; import org.apache.servicecomb.foundation.common.utils.RSAUtils; import org.apache.servicecomb.foundation.token.RSAKeypair4Auth; @@ -54,7 +53,8 @@ public class RSAConsumerTokenManager { PrivateKey privateKey = RSAKeypair4Auth.INSTANCE.getPrivateKey(); String instanceId = RegistryUtils.getMicroserviceInstance().getInstanceId(); String serviceId = RegistryUtils.getMicroservice().getServiceId(); - String randomCode = RandomStringUtils.randomAlphanumeric(128); + @SuppressWarnings("deprecation") + String randomCode = org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric(128); long generateTime = System.currentTimeMillis(); try { String plain = String.format("%s@%s@%s@%s", instanceId, serviceId, generateTime, randomCode); diff --git a/java-chassis-dependencies/pom.xml b/java-chassis-dependencies/pom.xml index 0847d69..343900e 100644 --- a/java-chassis-dependencies/pom.xml +++ b/java-chassis-dependencies/pom.xml @@ -335,7 +335,7 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> - <version>3.3.2</version> + <version>3.6</version> </dependency> <dependency> <groupId>commons-beanutils</groupId> diff --git a/java-chassis-distribution/src/release/LICENSE b/java-chassis-distribution/src/release/LICENSE index e166434..d9a3abd 100644 --- a/java-chassis-distribution/src/release/LICENSE +++ b/java-chassis-distribution/src/release/LICENSE @@ -347,7 +347,7 @@ Apache Commons BeanUtils (http://commons.apache.org/proper/commons-beanutils/) c Apache Commons Codec (http://commons.apache.org/proper/commons-codec/) commons-codec:commons-codec:jar:1.10 Apache Commons Collections (http://commons.apache.org/collections/) commons-collections:commons-collections:jar:3.2.2 Apache Commons Configuration (http://commons.apache.org/configuration/) commons-configuration:commons-configuration:jar:1.10 -Apache Commons Lang (http://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.3.2 +Apache Commons Lang (http://commons.apache.org/proper/commons-lang/) org.apache.commons:commons-lang3:jar:3.6 Apache Commons Logging (http://commons.apache.org/proper/commons-logging/) commons-logging:commons-logging:jar:1.2 Apache HttpClient (http://hc.apache.org/httpcomponents-client) org.apache.httpcomponents:httpclient:jar:4.5.2 Apache HttpCore (http://hc.apache.org/httpcomponents-core-ga) org.apache.httpcomponents:httpcore:jar:4.4.9 diff --git a/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.event.EventListener b/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.event.EventListener deleted file mode 100644 index b63d298..0000000 --- a/metrics/metrics-core/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.event.EventListener +++ /dev/null @@ -1,37 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -org.apache.servicecomb.metrics.core.event.InvocationStartExecutionEventListener -org.apache.servicecomb.metrics.core.event.InvocationStartedEventListener -org.apache.servicecomb.metrics.core.event.InvocationFinishedEventListener \ No newline at end of file
