概述
我们知道Google Guava的EventBus类使用了,register() 函数用来注册观察者,通过post() 函数发送消息的时候,并非把消息发送给所有的观察者,是观察者模式典型的应用
下面对案例做个简单的探究
demo
有如下这几个类,期间的关系如图所示:
可能会涉及到其他的东西,会加在代码注释中
目录结构及部分代码实例如下:
Controller类:
Event Bus的使用方式是通过registry注册到EventBus中,通过post通知相关的方法执行,所有核心是registry和post
public class UserControllerEventBus {
private EventBus eventBus;
public UserControllerEventBus(){
eventBus = new EventBus();
}
public String register(String telephone,String password) throws Exception {
UserService userService = new UserService();
Long userId = userService.register(telephone,password);
eventBus.registry(new SendMessageHandlerBus());
eventBus.registry(new SendEmailHandlerBus());
eventBus.registry(new SendMessageHandlerBus());
eventBus.post(userId);
return "register完成";
}
public static void main(String[] args) throws Exception {
UserControllerEventBus userController = new UserControllerEventBus();
String register = userController.register("1", "2");
System.out.println(register);
}
}
首先我们是对注解进行判断的,为此首先要定义一个注解
Subscribe注解
@Retention注解表示在何时使用,RUNTIME表示运行时
@Target注解表示作用在哪些方法上,METHOD表示方法
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Beta
public @interface Subscribe {
}
ObserverAction:ObserverAction类用来表示@Subscribe注解的方法,包含了我们需要作用的方法method和方法的对象object,因为只有通过这样才能调用相应的方法,execute中的参数是post传进来的,由Event Bus调用
public class ObserverAction {
private Method method;
private Object object;
public ObserverAction(Method method,Object object){
this.method = method;
this.object = object;
}
public void execute(Object param){
try {
method.invoke(object,param);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
Registry类:registry是核心类
public class Registry {
private ConcurrentHashMap<Class<?>, Collection<ObserverAction>> actionMap = new ConcurrentHashMap<>();
//注册
public void registry(Object obj){
Class<?> objClass = obj.getClass();
ConcurrentHashMap<Class<?>, Collection<ObserverAction>> map = getObserverAction(obj);
actionMap.putAll(map);
}
//返回所有的ObserverAction的List
public List<ObserverAction> getActionList(){
List<ObserverAction> observerActionList = new ArrayList<>();
for (Collection<ObserverAction> oneValues:actionMap.values()) {
observerActionList.addAll(oneValues);
}
return observerActionList;
}
public ConcurrentHashMap<Class<?>, Collection<ObserverAction>> getActionMap() {
return actionMap;
}
/*
一个类中存在多个@Subscribe指定的方法,每个@Subscribe指定的方法对应一个ObserverAction方法,
为此一个类对应多个ObserverAction方法
*/
private ConcurrentHashMap<Class<?>, Collection<ObserverAction>> getObserverAction(Object obj) {
ConcurrentHashMap<Class<?>, Collection<ObserverAction>> actionMap = new ConcurrentHashMap<>();
Class<?> aClass = obj.getClass();
List<ObserverAction> observerActions = new ArrayList<>();
//生成observeraction方法
for (Method oneMethod:checkMethodWithAnotation(obj) ) {
ObserverAction observerAction = new ObserverAction(oneMethod,obj);
observerActions.add(observerAction);
}
actionMap.put(aClass,observerActions);
return actionMap;
}
/*
一个类中有多个方法,这个类中的方法有的使用了指定注解,有的没,为此需要进行判断
获取到类注解上的方法,对方法的参数进行判断,有问题就抛出异常,没有问题则返回相应的方法
*/
private List<Method> checkMethodWithAnotation(Object object) {
List<Method> methodList = new ArrayList<>();
Class<?> objectClass = object.getClass();
Method[] declaredMethods = objectClass.getDeclaredMethods();
for (Method method:declaredMethods) {
//获取到它所有的方法,判断每个方法是否包含Subscribe注解
if (method.isAnnotationPresent(Subscribe.class)){
Class<?>[] parameterTypes = method.getParameterTypes();
//等于1不会抛出异常,不等于1会抛出异常
Preconditions.checkArgument(parameterTypes.length==1,"无法在Registr中注册");
//包含注解放到List中
methodList.add(method);
}
}
return methodList;
}
}