如何在项目启动时初始化一个管理员
在我们做初始化管理员的时候,我们是实现了一个Spring事件的监听类AppicationListener
,这个接口是基于java.util.EventListene的(继承)
这个接口有一个方法,就是处理容器事件的 -> onApplicationEvent(E event),这个E是ApplicationEvent的子类,而当时我们使用的是Spring刷新事件,这是因为Spring加载完Bean之后便会执行抛出事件。
代码如下:
public class AdminInitServiceImpl implements ApplicationListener<ContextRefreshedEvent>{
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
//要先判断数据中是否有管理员
...
//初始化系统体验金账户
...
}
Spring自定义发出事件
首先要明白什么是事件
- 事件:一个事件类型代表一种事件发生了,一个事件对象代表一个具体的事件发生了,一个事件对象需要关联。
- 事件源:事件源就是发出这个事件的本体,谁来发出这个事件的
而现在进行分析Spring的事件机制,事件是由ApplicationListener进行监听的,其实我们也可以很容易的发现,这个监听器其实是只能监听Spring容器内部的事件,既然这样,那么我就需要我的事件是可以传播到Spring容器内部的。
其实再想一想,Spring容器内部肯定有方法去扩散事件,这时找到Spring容器类ApplicationContext
,发现这个类继承了一个类ApplicationEventPublisher
,根据类名可以判断类里面有方法将事件扩散。这个方法就是
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
所以只需要调用Spring容器对象的这个方法将我们的事件传播到Spring内部即可。
自定义Spring事件
怎么发出事件已经知道了,那怎么自定义我们自己的事件呢?其实也很简单,自定义一个类继承ApplicationEvent
即可,并且我们还需要复写它的构造器,变成我们自己的,为什么要复写构造器,其实观察ApplicationEvent
这个抽象类的构造器就可以发现这里有一个设置时间的方法,所以可以判断每一个事件对象应该要不一样的。
示例
- 首先定义好事件
@Getter
public class RealAuthEvent extends ApplicationEvent {
private RealAuth realAuth;
//编写构造器,业务
public RealAuthEvent(Object source, RealAuth realAuth) {
super(source);
this.realAuth = realAuth;
}
}
基础回顾:这里不写上构造器会报错,因为如果不写构造器,系统会自动给这个类加上一个无参的构造器,这是在父类有无参构造器的情况下,因为初始化子类一定要先初始化父类,所以会调用父类的构造器,也就是什么都不写的情况下,java会隐式的加上super,而如果父类手动加了有参构造器,并且没有无参的构造器,子类也就必须要显示的在自己的构造器中用super调用父类的构造器。
这里我们自定的构造器写了两个参数,因为其一,父类的构造器需要souce参数,其二,就是我们需要利用这个事件对象传递我们自己的realAuth业务对象
- 在事件源中引入ApplicationContext对象,调用
publishEvent
方法
@Autowired
private ApplicationContext ctx;
...
ctx.publishEvent(new RealAuthEvent(this,realAuth));
- 定义一个service实现
ApplicationListener
来监听自定义事件
@Service
public class SendMessageServiceImpl implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof RealAuthEvent ){//这里是为了将多个自定义事件放在同一个service里面来处理
RealAuthEvent realAuthEvent = (RealAuthEvent)event;
//拿到业务参数
RealAuth realAuth = realAuthEvent.getRealAuth();//因为自定义的事件中设置了RealAuth对象进去,所以我们可以拿到
//执行相关的业务
}
}
}