guava eventbus不支持spring的aop代理

14-04-11 wilsonp
                   

今天在使用guava eventbus发送事件的时候,post之后没有进入相应的处理方法断点中,发觉很奇怪,然后就看了看eventbus的源代码,其中有一处:

public void register(Object object) {

Multimap<Class<?>, EventSubscriber> methodsInListener =

finder.findAllSubscribers(object);

subscribersByTypeLock.writeLock().lock();

try {

subscribersByType.putAll(methodsInListener);

} finally {

subscribersByTypeLock.writeLock().unlock();

}

}

@Override

public Multimap<Class<?>, EventSubscriber> findAllSubscribers(Object listener) {

Multimap<Class<?>, EventSubscriber> methodsInListener = HashMultimap.create();

Class<?> clazz = listener.getClass();

for (Method method : getAnnotatedMethods(clazz)) {

Class<?>[] parameterTypes = method.getParameterTypes();

Class<?> eventType = parameterTypes[0];

EventSubscriber subscriber = makeSubscriber(listener, method);

methodsInListener.put(eventType, subscriber);

}

return methodsInListener;

}

发现findAllSubscribers方法中的 Class<?> clazz = listener.getClass();代码只是获取监听器的class对象,但此时spring已经对该监听器生成了代理类,所以获取到的始终都是proxy,而在这个proxy对象中没有相关的处理方法,所以根本就没有注册成功,所以就进入不了断电了,想修改源代码来支持spring的代理类,还在实践中....

不知道有没有童鞋已经遇到这个问题并有其他的解决方案的没?

                   

lostalien
2014-04-12 10:10

请问你把 guava eventbus 用在什么场景或者什么类型的项目下啦?

wilsonp
2014-04-15 09:43

用在了cqrs的event机制上了,因为是异步的,且不需要执行结果,但是命令总线部分需要执行结果,所以命令总线是自己实现的。

问题我自己解决了,因为guava eventbus在注册的时候只是简单的从注册类中查找对应的监听器,所以在注册之前先判断是否是代理类(spring的代理类都是包含‘$’),如果是代理类就将代理类中的源对象找出来,然后注册源对象:

private IEventHandler findProxySource(IEventHandler handler){

Method getTargetSource = null;

try {

try {

getTargetSource = handler.getClass().getDeclaredMethod("getTargetSource");

Object singletonTargetSource = getTargetSource.invoke(handler, new Object[]{});

Method getTarget = singletonTargetSource.getClass().getDeclaredMethod("getTarget");

Object target = getTarget.invoke(singletonTargetSource, new Object[]{});

return (IEventHandler)target;

} catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {

e.printStackTrace();

}

} catch (SecurityException e) {

e.printStackTrace();

}

return null;

}

这样就可以注册成功了

MartinChen
2014-04-16 14:21

这个原因可能是因为 spring用的动态代理模式,代理类丢失的注解等信息,

在spring配置中加上

<aop:aspectj-autoproxy proxy-target-class="true"/>

也许可以解决你的问题

yubinjiayou
2018-04-16 14:29

你这个问题是怎么解决的,从哪里判断代理类,麻烦告之一下, 谢谢