spring自带事件功能,继承自jdk中的事件,事件其实是用的观察者设计模式,spring容器在启动时,把所有的lisenter存起来,当发布事件时,再循环lisenter集合,然后调用。
写一个事件发布者,MyEvent是我自己定的一个实体类,代表事件的主体,注入ApplicationContext,ApplicationContext继承了ApplicationEventPublisher,真正的实现在org.springframework.context.support.AbstractApplicationContext这个类中。
@Component
public class MyPublisher{
@Autowired
private ApplicationContext applicationContext;
/**
* 自己定义的发布事件 用ApplicationContext发布
* @param myEvent
*/
public void publisMess(MyEvent myEvent){
applicationContext.publishEvent(myEvent);
}
}
源码中有两个方法,spring4.2以后,发布事件可以不用继承ApplicationEvent,可以用任意类型当事件
public void publishEvent(ApplicationEvent event) {
this.publishEvent(event, (ResolvableType)null);
}
public void publishEvent(Object event) {
this.publishEvent(event, (ResolvableType)null);
}
我的事件实体继承了ApplicationEvent,重写了构造方法,把我自己定义的EventBody实体传了进去
/**
* spring事件要继承ApplicationEvent,它继承的jdk的事件EventObject
*/
public class MyEvent extends ApplicationEvent {
private EventBody eventBody;
public EventBody getEventBody() {
return eventBody;
}
public void setEventBody(EventBody eventBody) {
this.eventBody = eventBody;
}
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public MyEvent(EventBody source) {
super(source);
this.eventBody = source;
}
}
public class EventBody {
private String name;
private String message;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public EventBody() {
}
public EventBody(String name, String message) {
this.name = name;
this.message = message;
}
@Override
public String toString() {
return "EventBody{" +
"name='" + name + '\'' +
", message='" + message + '\'' +
'}';
}
}
接收事件有两种方法
1.传统方法继承ApplicationListener
@Component
public class EvenLisenterConfig implements ApplicationListener {
@Override
public void onApplicationEvent(MyEvent myEvent) {
System.out.println("接收到事件了1");
}
}
2.用EventListener注解,如果不需要参数,事件也可以不用放在方法参数中,在@EventListener中指定类型也可以。
@Component
public class AnnoEventLisenterConfig {
@EventListener(MyEvent.class)
public void myEventLisenter2(){
System.out.println("接收到事件了2");
}
@Async
@EventListener
public void myEventLisenter3(MyEvent myEvent){
System.out.println(myEvent.getEventBody().toString());
}
}
@Async是做了异步。
方法中也可以加入返回参数,如果有返回参数,返回参数也会当事件发布出去。
EventListener源码如下,还可以用SpEL表达式
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventListener {
/**
* Alias for {@link #classes}.
*/
@AliasFor("classes")
Class>[] value() default {};
/**
* The event classes that this listener handles.
* If this attribute is specified with a single value, the
* annotated method may optionally accept a single parameter.
* However, if this attribute is specified with multiple values,
* the annotated method must not declare any parameters.
*/
@AliasFor("value")
Class>[] classes() default {};
/**
* Spring Expression Language (SpEL) attribute used for making the
* event handling conditional.
*
Default is {@code ""}, meaning the event is always handled.
*
The SpEL expression evaluates against a dedicated context that
* provides the following meta-data:
*
* - {@code #root.event}, {@code #root.args} for
* references to the {@link ApplicationEvent} and method arguments
* respectively.
* - Method arguments can be accessed by index. For instance the
* first argument can be accessed via {@code #root.args[0]}, {@code #p0}
* or {@code #a0}. Arguments can also be accessed by name if that
* information is available.
*
*/
String condition() default "";
}
**实时内容请关注微信公众号,公众号与博客同时更新:程序员星星**