在Spring中发布自定义事件(精)
- 格式:doc
- 大小:18.00 KB
- 文档页数:5
在Spring中发布自定义事件
(2008-01-24 08:53:11
在Java中,事件机制的实现包括三个基本组件,事件、事件发布者和事件监听者。在
Spring中,事件机制的实现也同样包括这三个基本组件,但Spring框架对这些组件实现了高层
封装和抽象,使得事件的发布过程非常的简单,而且降低了组件之间的耦合性。但事情总没有
完美的,事件组件和Spring框架之间的耦合则不可避免。不管怎样,Spring还是帮助我们简单
而优雅的实现了事件机制。下面就来看看如何在Spring中实现自定义事件的发布和监听。
假设这样一个场景:新学期开了一门新课,学生要通过注册取得上课的资格,课程不可能接
受太多的学生,当注册人数达到一定数量后,就不再允许注册这门课程了(我们这门新课只接
受7个学生,先到先得哦)。
先实现和事件没关系的组件——课程,代码如下:
public class Course {
public static final int MAX_CAPACITY = 7;
private int capacity = 0;
public Course( {}
public int getCapacity( {
return capacity;
}
public void addNewStudent( {
this.capacity++;
}
}
接着实现事件的三个基本组件,首先事件是事件机制的核心,先实现它。这里实现了两个事
件RegisteredEvent和CourseFullEvent,分别表示注册成功事件和课程已满事件。在Spring
中,所有事件都继承自抽象类ApplicationEvent。我们不需要这两个事件做什么,所以它们的
代码很简单。
public class RegisteredEvent extends ApplicationEvent {
public RegisteredEvent(Object arg0 {
super(arg0;
}
}
public class CourseFullEvent extends ApplicationEvent {
public CourseFullEvent(Object arg0 {
super(arg0;
}
}
第二个组件是事件发布者,也就是课程注册服务。在Spring中发布事件当然要通过容器来发
布,这样容器内的监听器组件才会知道事件发生了。BeanFactory容器没有发布事件的功能,
所以就要用特性更为丰富的ApplicationContext。而容器中的Java对象要想知道它所在的容
器,就一定要实现ApplicationContextAware接口,因此这个对象就难免要和Spring框架建立联
系了,为了实现发布事件的功能,与框架的耦合在所难免。
public interface StudentService {
void register(Course course, Student student;
}
public class StudentServiceImpl implements StudentService,
ApplicationContextAware {
private ApplicationContext context;
public void setApplicationContext(ApplicationContext arg0
throws BeansException {
this.context = arg0;
}
public void register(Course course, Student student {
int capacity = course.getCapacity(;
if (++capacity > Course.MAX_CAPACITY {
System.out.println("该课程已经人满,注册失败";
context.publishEvent(new CourseFullEvent(this;
} else {
course.addNewStudent(;
student.setStudentId(course.getCapacity(;
System.out.println("恭喜您,注册成功";
context.publishEvent(new RegisteredEvent(this;
}
}
}
Spring容器会自动地通过set方法把自己注入到实现了ApplicationContextAware接口的对象
中,这样StudentService的实现就可以通过所在的容器发布任何事件了,很简单,调用容器的
publishEvent方法并传入所要发布的事件就行了。
最后要实现的组件就是监听者了,也就是Student,它实现了ApplicationListener接口,并把
自己注册到Spring容器中。当事件发生时,容器会通知它里面的监听者,Student收到事件通
知,在onApplicationEvent方法中,判断事件类型,并对事件做出响应。Student的代码如下:
public class Student implements ApplicationListener {
private int studentId;
public Student( {}
public void onApplicationEvent(ApplicationEvent arg0 {
if (arg0 instanceof RegisteredEvent {
System.out.println("太好了,我注册的学号是" + this.studentId;
} else if (arg0 instanceof CourseFullEvent {
System.out.println("来晚了,我没注册上";
}
}
public void setStudentId(int studentId {
this.studentId = studentId;
}
}
当然,别忘了Spring的配置文件:
com.Student " />
com.Course " />
studentService "
class="com.StudentServiceImpl" />
最后,写个小应用运行一下,看看效果如何:
public class SpecialBeanApp {
public static void main(String[] args {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml";
// 开一门课
Course course = (Course ctx.getBean("course";
// 开启注册课程的服务
StudentService service = (StudentService ctx.getBean("studentService";
// 注册10个学生
for (int i = 0; i < 10; i++ {
Student student = (Student ctx.getBean("student";
service.register(course, student;
}
}
}
最后再说明一点,Spring的事件机制是同步的,也就是阻塞式的,所以,对事件的处理要尽
量简单快捷,否则会极大的影响应用程序的性能。我们期待着Spring2.0的后续版本能实现异
步的事件机制。