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。