Skip to content

Commit a91c4b9

Browse files
committed
1,commons引入eventbus;2,JsonUtil方法加入异常日志
1 parent b9ffa72 commit a91c4b9

File tree

6 files changed

+215
-1
lines changed

6 files changed

+215
-1
lines changed

jforgame-commons/src/main/java/jforgame/commons/JsonUtil.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import com.fasterxml.jackson.databind.ObjectMapper;
99
import com.fasterxml.jackson.databind.type.ArrayType;
1010
import com.fasterxml.jackson.databind.type.TypeFactory;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
1113

1214
import java.io.StringWriter;
1315
import java.util.Collection;
@@ -20,6 +22,8 @@
2022
*/
2123
public class JsonUtil {
2224

25+
private static Logger logger = LoggerFactory.getLogger(JsonUtil.class);
26+
2327
private static final TypeFactory typeFactory = TypeFactory.defaultInstance();
2428

2529
private static final ObjectMapper MAPPER = new ObjectMapper();
@@ -37,6 +41,7 @@ public static String object2String(Object object) {
3741
try {
3842
MAPPER.writeValue(writer, object);
3943
} catch (Exception e) {
44+
logger.error("", e);
4045
return null;
4146
}
4247
return writer.toString();
@@ -48,6 +53,7 @@ public static <T> T string2Object(String json, Class<T> clazz) {
4853
try {
4954
return (T) MAPPER.readValue(json, type);
5055
} catch (Exception e) {
56+
logger.error("", e);
5157
return null;
5258
}
5359
}
@@ -57,6 +63,7 @@ public static String map2String(Map<?, ?> map) {
5763
try {
5864
MAPPER.writeValue(writer, map);
5965
} catch (Exception e) {
66+
logger.error("", e);
6067
return null;
6168
}
6269
return writer.toString();
@@ -67,6 +74,7 @@ public static Map<String, Object> string2Map(String json) {
6774
try {
6875
return MAPPER.readValue(json, type);
6976
} catch (Exception e) {
77+
logger.error("", e);
7078
return null;
7179
}
7280
}
@@ -76,6 +84,7 @@ public static <K, V> Map<K, V> string2Map(String json, Class<K> keyClazz, Class<
7684
try {
7785
return MAPPER.readValue(json, type);
7886
} catch (Exception e) {
87+
logger.error("", e);
7988
return null;
8089
}
8190
}
@@ -84,8 +93,9 @@ public static <K, V> Map<K, V> string2Map(String json, Class<K> keyClazz, Class<
8493
public static <T> T[] string2Array(String json, Class<T> clazz) {
8594
ArrayType type = typeFactory.constructArrayType(clazz);
8695
try {
87-
return (T[]) MAPPER.readValue(json, type);
96+
return MAPPER.readValue(json, type);
8897
} catch (Exception e) {
98+
logger.error("", e);
8999
return null;
90100
}
91101
}
@@ -95,6 +105,7 @@ public static <C extends Collection<E>, E> C string2Collection(String json, Clas
95105
try {
96106
return MAPPER.readValue(json, type);
97107
} catch (Exception e) {
108+
logger.error("", e);
98109
return null;
99110
}
100111
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package jforgame.commons.eventbus;
2+
3+
/**
4+
* 事件基类
5+
*/
6+
public interface BaseEvent {
7+
8+
default Object getOwner() {
9+
return "system";
10+
}
11+
12+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package jforgame.commons.eventbus;
2+
3+
import jforgame.commons.thread.NamedThreadFactory;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
7+
import java.util.Set;
8+
import java.util.concurrent.Executor;
9+
import java.util.concurrent.Executors;
10+
11+
/**
12+
* 事件总线
13+
* 推荐使用单例模式获取实例
14+
*/
15+
public class EventBus {
16+
17+
private Logger logger = LoggerFactory.getLogger(getClass());
18+
19+
private Executor executor;
20+
21+
private SubscriberRegistry registry;
22+
23+
24+
public EventBus () {
25+
// 异步执行的需求很少,一条线程就够了
26+
this.executor = Executors.newSingleThreadExecutor(new NamedThreadFactory("EventBus-Async-Thread"));
27+
this.registry = new SubscriberRegistry();
28+
}
29+
30+
/**
31+
* 从指定订阅者注册所有的事件监听
32+
* 该方法会寻找订阅者类中所有被@Subscribe注解标记的方法,并注册到事件总线中
33+
* @param subscriber 订阅者对象
34+
*/
35+
public void register(Object subscriber) {
36+
registry.register(subscriber);
37+
}
38+
39+
/**
40+
* 同步处理事件
41+
*
42+
* @param event
43+
*/
44+
public void post(BaseEvent event) {
45+
Class<? extends BaseEvent> eventType = event.getClass();
46+
Set<Subscriber> subscribers = registry.getSubscribersForEvent(eventType);
47+
48+
subscribers.forEach((subscriber) -> {
49+
try {
50+
subscriber.handleEvent(event);
51+
} catch (Exception e) {
52+
logger.error("", e);
53+
}
54+
});
55+
}
56+
57+
/**
58+
* 异步处理事件
59+
*
60+
* @param event
61+
*/
62+
public void asyncPost(BaseEvent event) {
63+
this.executor.execute(() -> {
64+
post(event);
65+
});
66+
}
67+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package jforgame.commons.eventbus;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* 事件订阅
10+
*/
11+
@Retention(RetentionPolicy.RUNTIME)
12+
@Target(ElementType.METHOD)
13+
public @interface Subscribe {
14+
15+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package jforgame.commons.eventbus;
2+
3+
import java.lang.reflect.InvocationTargetException;
4+
import java.lang.reflect.Method;
5+
6+
/**
7+
* 具体事件订阅者
8+
*/
9+
class Subscriber {
10+
11+
/**
12+
* 事件处理者
13+
*/
14+
private Object listener;
15+
16+
private Method method;
17+
18+
public Subscriber(Object listener, Method method) {
19+
super();
20+
this.listener = listener;
21+
this.method = method;
22+
}
23+
24+
public void handleEvent(BaseEvent event) throws InvocationTargetException {
25+
try {
26+
method.invoke(listener, event);
27+
} catch (IllegalArgumentException e) {
28+
throw new Error("Method rejected target/argument: " + event, e);
29+
} catch (IllegalAccessException e) {
30+
throw new Error("Method became inaccessible: " + event, e);
31+
} catch (InvocationTargetException e) {
32+
if (e.getCause() instanceof Error) {
33+
throw (Error) e.getCause();
34+
}
35+
throw e;
36+
}
37+
}
38+
39+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package jforgame.commons.eventbus;
2+
3+
import java.lang.reflect.Method;
4+
import java.util.ArrayList;
5+
import java.util.Collections;
6+
import java.util.HashMap;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Set;
10+
import java.util.concurrent.ConcurrentHashMap;
11+
import java.util.concurrent.ConcurrentMap;
12+
import java.util.concurrent.CopyOnWriteArraySet;
13+
14+
/**
15+
* 订阅者注册表
16+
*/
17+
class SubscriberRegistry {
18+
19+
private final ConcurrentMap<Class<? extends BaseEvent>, CopyOnWriteArraySet<Subscriber>> subscribers = new ConcurrentHashMap<>();
20+
21+
void register(Object subscriber) {
22+
Map<Class<? extends BaseEvent>, Subscriber> listenerMethods = findAllSubscribers(subscriber);
23+
24+
for (Map.Entry<Class<? extends BaseEvent>, Subscriber> entry : listenerMethods.entrySet()) {
25+
Class<? extends BaseEvent> eventType = entry.getKey();
26+
27+
subscribers.putIfAbsent(eventType, new CopyOnWriteArraySet<>());
28+
CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);
29+
30+
eventSubscribers.add(entry.getValue());
31+
}
32+
}
33+
34+
private Map<Class<? extends BaseEvent>, Subscriber> findAllSubscribers(Object listener) {
35+
Map<Class<? extends BaseEvent>, Subscriber> methodsInListener = new HashMap<>();
36+
Class<?> clazz = listener.getClass();
37+
for (Method method : getAnnotatedMethods(clazz)) {
38+
Class<?>[] parameterTypes = method.getParameterTypes();
39+
@SuppressWarnings("unchecked")
40+
Class<? extends BaseEvent> eventType = (Class<? extends BaseEvent>) parameterTypes[0];
41+
methodsInListener.put(eventType, new Subscriber(listener, method));
42+
}
43+
return methodsInListener;
44+
}
45+
46+
private static List<Method> getAnnotatedMethods(Class<?> clazz) {
47+
List<Method> result = new ArrayList<>();
48+
for (Method method : clazz.getDeclaredMethods()) {
49+
if (method.isAnnotationPresent(Subscribe.class)) {
50+
Class<?>[] parameterTypes = method.getParameterTypes();
51+
if (parameterTypes.length != 1) {
52+
throw new IllegalArgumentException(
53+
"Method " + method.getName() + " has @Subscribe annotation but has" + parameterTypes.length
54+
+ " parameters." + "Subscriber methods must have exactly 1 parameter.");
55+
56+
}
57+
result.add(method);
58+
}
59+
}
60+
return result;
61+
}
62+
63+
public Set<Subscriber> getSubscribersForEvent(Class<? extends BaseEvent> eventType) {
64+
if (!subscribers.containsKey(eventType)) {
65+
return Collections.emptySet();
66+
}
67+
return subscribers.get(eventType);
68+
}
69+
70+
}

0 commit comments

Comments
 (0)