Java spring通用应用程序事件无法到达目标

Java spring通用应用程序事件无法到达目标,java,spring,Java,Spring,我有下面的弹簧支架。其思想是,它保留某个对象的实例,并在该对象发生更改时触发更改事件(提供旧值和新值): 公共类持有者实现ApplicationEventPublisherAware{ 私有最终类payloadType;//因为java泛型不完整 private T curr;//持有的最新值 私有应用程序EventPublisher publisher;//spring上下文引用 公众持有人(类别payloadType){ this.payloadType=payloadType; } pub

我有下面的弹簧支架。其思想是,它保留某个对象的实例,并在该对象发生更改时触发更改事件(提供旧值和新值):

公共类持有者实现ApplicationEventPublisherAware{
私有最终类payloadType;//因为java泛型不完整
private T curr;//持有的最新值
私有应用程序EventPublisher publisher;//spring上下文引用
公众持有人(类别payloadType){
this.payloadType=payloadType;
}
public void change()引发异常{
T prev=当前值;
curr=payloadType.newInstance();
publisher.publishEvent(新内容schangedevent(prev,curr));
}
}
然后我有一个listener类对这些事件做出反应:

@Named
public class Listener {

    @EventListener
    public void onChange(ContentsChangedEvent<Cat> event) {
        //never gets called
    }

    @EventListener
    public void onErasedChange(ContentsChangedEvent<?> event) {
        //does get called
    }
}
@Named
公共类侦听器{
@事件监听器
更改后的公共作废(内容更改事件){
//从未接到过电话
}
@事件监听器
公共无效onErasedChange(内容更改事件){
//有人打电话吗
}
}
我的问题是,永远不会调用通用(正确)事件侦听器方法(获取
事件的方法),而只调用已擦除的方法

为了完整起见,这里是spring context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.2.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="net.radai"/>

    <bean id="holder" class="net.radai.Holder">
        <constructor-arg type="java.lang.Class" value="net.radai.Cat"/>
    </bean>
</beans>

我还把整个事情都放到github上了-。这是一个maven项目——你构建它,你会得到一个失败的测试

我做错了什么


注意:在这个实际用例中,我希望有多个这样的持有者,并强制所有侦听器在不可接受的
公共类内容中丢弃与它们无关的事件{
public class ContentsChangedEvent<T> extends ApplicationEvent{

    public ContentsChangedEvent(Holder<T> source, T prev, T curr) {
        super(source);
        this.prev = prev;
        this.curr = curr;
    }                                  

}   

//Holder class
public void change() {
        T prev = curr;
        try {
        curr = payloadType.newInstance();
        } catch (Exception e) {
            int g = 8;
        }
        publisher.publishEvent(new ContentsChangedEvent<T>(this, prev, curr));
 }
公共内容转让(持有人来源,T上一个,T当前){ 超级(来源); this.prev=prev; this.curr=curr; } } //持有人类别 公共空间更改(){ T prev=当前值; 试一试{ curr=payloadType.newInstance(); }捕获(例外e){ int g=8; } publisher.publishEvent(新内容schangedevent(this,prev,curr)); }

onChange和onErasedChange都将被调用

如果在泛型事件类中实现org.springframework.core.ResolvableTypeProvider,则侦听器将解析它。 例如:

import org.springframework.core.ResolvableType;
import org.springframework.core.ResolvableTypeProvider;

public class EventBase<T> {
    public T payload;
}

public class AppEvent<T> extends EventBase<T> implements ResolvableTypeProvider {
    @Override
    public ResolvableType getResolvableType() {
        return ResolvableType.forClassWithGenerics(
            getClass(), 
            ResolvableType.forInstance(this.payload)
        );
    }
}

@Component
public class EventHandler {
    @EventListener
    public void handleString(AppEvent<String> event) {
       System.out.println("Event[" + event.getClass().getSimpleName() + "], received:" + event);
    }
    
    @EventListener
    public void handleLong(AppEvent<Long> event) {
       System.out.println("Event[" + event.getClass().getSimpleName() + "], received:" + event);
    }

}
import org.springframework.core.ResolvableType;
导入org.springframework.core.ResolvableTypeProvider;
公共类事件库{
公共T载荷;
}
公共类AppEvent扩展EventBase实现ResolvableTypeProvider{
@凌驾
公共ResolvableType getResolvableType(){
返回ResolvableType.ForClassWith泛型(
getClass(),
例如(this.payload)
);
}
}
@组成部分
公共类事件处理程序{
@事件监听器
公共无效处理(上诉事件){
System.out.println(“事件[”+Event.getClass().getSimpleName()+”],收到:“+Event”);
}
@事件监听器
公共无效handleLong(上诉事件){
System.out.println(“事件[”+Event.getClass().getSimpleName()+”],收到:“+Event”);
}
}

Spring正在将事件转换为“PayloadApplicationEvent”,并因此调用通配符侦听器方法。
公共类ContentsChangedEvent扩展了ApplicationEvent{public ContentsChangedEvent(Holder source,T prev,T curr){super(source);this.prev=prev;this.curr=curr;}}//Holder类public void change(){T prev=curr;try{curr=payloadType.newInstance();}catch(异常e){int g=8;}publisher.publishEvent(新内容schangedevent(this,prev,curr));}
onChange和onErasedChange都将被调用。你需要通配符侦听器方法吗?@Sanj-不,我不需要通配符侦听器。谢谢-您的解决方案有效。如果您可以将其表述为一个答案,我可以结束这个问题:-)或者,作为一个替代方案,spring的一个小补丁可以让我避免扩展ApplicationEvent-显然,从现在开始,spring Boot 2.4.5的新spring发行版中不需要这样做
import org.springframework.core.ResolvableType;
import org.springframework.core.ResolvableTypeProvider;

public class EventBase<T> {
    public T payload;
}

public class AppEvent<T> extends EventBase<T> implements ResolvableTypeProvider {
    @Override
    public ResolvableType getResolvableType() {
        return ResolvableType.forClassWithGenerics(
            getClass(), 
            ResolvableType.forInstance(this.payload)
        );
    }
}

@Component
public class EventHandler {
    @EventListener
    public void handleString(AppEvent<String> event) {
       System.out.println("Event[" + event.getClass().getSimpleName() + "], received:" + event);
    }
    
    @EventListener
    public void handleLong(AppEvent<Long> event) {
       System.out.println("Event[" + event.getClass().getSimpleName() + "], received:" + event);
    }

}