4 Spring ApplicationListener 问题版

ApplicationListener系列文章

  1. ApplicationListener 基础版

  2. ApplicationListener 进阶版

  3. ApplicationListener源码版

  4. ApplicationListener 问题版

  5. ApplicationListener 扩展版

  6. ApplicationListener 总结版

为什么监听器不起作用

先说场景:事件的数据源通过泛型进行抽象,通过不同的数据源类型,代表不同的业务场景,例如:OrgInfo是事件的基础数据,OrgAddInfo代表新增,OrgDeleteInfo代表删除等。然后根据不同的数据类型,创建监听,但是发现只有OrgInfo的监听生效了,并且是多次生效,其他监听都不生效。

数据

基础数据

@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrgInfo implements Serializable {
    private Integer id;
    private String name;

    @Override
    public String toString() {
        return "OrgInfo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

业务扩展数据

@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrgAddInfo extends OrgInfo {
    private String address;

    public OrgAddInfo(int id, String name, String address) {
        super(id, name);
        this.address = address;
    }

    @Override
    public String toString() {
        return "OrgAddInfo{" +
                "address='" + address + '\'' +
                "} " + super.toString();
    }
}

事件

请注意:该事件的数据是带有泛型约束。<S extends OrgInfo>:通过泛型约束,事件的数据源既可以是OrgInfo,也可以是OrgAddInfo,是不是可以通过这种形式,实现一个事件多个业务操作(机构变更事件:新增操作、修改操作、删除操作)?

public class OrgChangeEvent<S extends OrgInfo> extends ApplicationEvent {

    public OrgChangeEvent(S source) {
        super(source);
    }

    public S getSource() {
        return (S) super.getSource();
    }
}

监听

新增操作的监听

public class OrgAddListener implements ApplicationListener<OrgChangeEvent<OrgAddInfo>> {
    @Override
    public void onApplicationEvent(OrgChangeEvent<OrgAddInfo> event) {
        System.out.println("org info event add " + event.toString());
    }
}

普通操作的监听

public class OrgListener implements ApplicationListener<OrgChangeEvent<OrgInfo>> {
    @Override
    public void onApplicationEvent(OrgChangeEvent<OrgInfo> event) {
        System.out.println("org info event:" + event.toString());
    }
}

发布事件

public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
       applicationContext.register(OrgListener.class);
        applicationContext.register(OrgAddListener.class);
        applicationContext.refresh();

        applicationContext.publishEvent(new OrgChangeEvent(new OrgInfo(1, "orgInfo")));
        applicationContext.publishEvent(new OrgChangeEvent<OrgAddInfo>(new OrgAddInfo(1, "orgInfoAdd","地址")));
 }

        

输出内容

org info event:com.jkf.event.listener.org.event.OrgChangeEvent[source=OrgInfo{id=1, name=‘orgInfo’}]

org info event:com.jkf.event.listener.org.event.OrgChangeEvent[source=OrgAddInfo{address=‘地址’} OrgInfo{id=1, name=‘orgInfoAdd’}]

全部都是:OrgListener 的输出,并且输出了两次,说明OrgAddListener 的输出并没有生效。

原因

因为 applicationContext.publishEvent*(new OrgChangeEvent(new OrgInfo(1, “orgInfo”)))*

1 根据smartListener.supportsEventType*(eventType):OrgListener肯定能消费new OrgChangeEvent(new OrgInfo(1, “orgInfo”)),第一个输出没有问题。*

2 new OrgChangeEvent*<OrgAddInfo>(new OrgAddInfo(1, “orgInfoAdd”,“地址”)):OrgChangeEvent在ResolvableType中被识别为OrgChangeEvent<?>,因此在ResolvableType.isAssignableFrom中的泛型比较时,被解析为OrgInfo类,但是监听的数据是OrgAddInfo,两者不同,导致第二个监控未生效。*

结论

因为泛型擦除的原因,OrgAddInfo被识别成OrgInfo,因此通过sourceType区分不同的事件时无法实现的,因此只能通过:OrgAddEvent、OrgEditEvent、OrgDeleteEvent,三者都继承了OrgEvent,OrgEvent持有OrgInfo信息,这样来实现OrgInfo的不同操作对应不同的Listener。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值