For Handling of Events, there are first 3 core things that is necessary.
In this blog, we will try 3 different ways to implement event handling using Spring. First from simple direct usage of Spring and then to a method where the business logic is decoupled from direct Spring usage.
Using Spring Framework ApplicationEvent we will create a OfferEvent class.
//implemented method
public void service(){
- Event
- Event Publisher
- Event Listener
In this blog, we will try 3 different ways to implement event handling using Spring. First from simple direct usage of Spring and then to a method where the business logic is decoupled from direct Spring usage.
Method 1 : Simple Direct Usage of Spring Framework
Event
Using Spring Framework ApplicationEvent we will create a OfferEvent class.
package com.test2;
import org.springframework.context.ApplicationEvent;
public class OfferEvent extends ApplicationEvent{
private static final long serialVersionUID =
3029215982265408049L;
public OfferEvent(Object
source) {
super(source);
// TODO Auto-generated
constructor stub
}
public String toString(){
return "OfferEvent2";
}
}
Event Publisher
Using ApplicationEventPublisherAware Interface we will be able to set the ApplicationEventPublisher from the Spring Context to publish our events.
package com.test2;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
public class Service implements ApplicationEventPublisherAware
{
private ApplicationEventPublisher
publisher;
//implemented method
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)
{
this.publisher = applicationEventPublisher;
}
public void service(){
OfferEvent event = new OfferEvent(this);
this.publisher.publishEvent(event);
this.publisher.publishEvent(event);
}
}
Event Listener
Using ApplicationListener of Spring Framework, we can listen to ApplicationEvents and perform actions when an event occurs.
package com.test2;
import org.springframework.context.ApplicationListener;
public class OfferEventListener
implements ApplicationListener<OfferEvent> {
//implemented
method
public void onApplicationEvent(OfferEvent event) {
System.out.println("OfferEvent received =" + event.getClass()
+
"\n
At ="
+ event.getTimestamp()
+
"\n
Source =" + event.getSource().getClass()
+
"\n
Msg =" + event.toString() );
}
}
Main application
package com.test2;
import org.springframework.context.support.AbstractApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args)
{
AbstractApplicationContext ctx
= new ClassPathXmlApplicationContext("springbeanconfig02.xml");
Service
serv = (Service)ctx.getBean("ServiceBean");
serv.service();
ctx.registerShutdownHook();
}
}
Spring Bean XML Configuration
<?xml version="1.0"
encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="ServiceBean" class="com.test2.Service"></bean>
<bean class="com.test2.OfferEventListener"></bean>
</beans>
Issue
In this implementation the ApplicationEvent dependency is hardcoded into Service class which means for this Service to use any different type of ApplicationEvent we have to rewrite the code. We can solve this using next Method.
Method2: Injecting ApplicationEvent Dependency using Spring
In Service class using setEvent we will inject ApplicationEvent from a Spring XML bean configuration.
package com.test3;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
public class Service implements ApplicationEventPublisherAware
{
private ApplicationEventPublisher
publisher;
private ApplicationEvent
event;
public void setEvent(ApplicationEvent event) {
this.event = event;
}
//implemented
method
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)
{
this.publisher = applicationEventPublisher;
}
public void service(){
this.publisher.publishEvent(this.event);
}
}
Spring Bean XML
<?xml version="1.0"
encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="ServiceBean" class="com.test3.Service">
<property name="event">
<ref bean="OfferEventBean" />
</property>
</bean>
<bean id="OfferEventBean" class="com.test3.OfferEvent">
<constructor-arg>
<ref bean="ServiceBean" />
</constructor-arg>
</bean>
<bean class="com.test3.OfferEventListener"></bean>
</beans>
Issue
In this implementation, the main business class Service is directly dependent on Spring ApplicationEventPublisherAware interface, ApplicationEventPublisher, and ApplicationEvent. So the issue is it would be difficult to change in future if we wish to use any other tool or framework. We can solve this using the next method.
Method3: Event Handling without Business Logic having Direct Dependence on Spring
Inorder to Decouple the Business Logic class from the Spring framework, first we will create our version of ApplicationEvent.
package com.test4;
import org.springframework.context.ApplicationEvent;
public abstract class MyAppEvent
extends ApplicationEvent{
private static final long serialVersionUID =
-6092666752131453519L;
public MyAppEvent(Object
source) {
super(source);
}
}
Now for every ApplicationEvents which we wish to create we will extend that from MyAppEvent.
package com.test4;
public class OfferEvent extends MyAppEvent{
private static final long serialVersionUID =
-2857555740801485476L;
public OfferEvent(Object
source) {
super(source);
}
public String toString(){
return "OfferEvent4";
}
}
We will also create a our version of ApplicationEventPublisher.
package com.test4;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
public class MyAppEventPublisher
implements ApplicationEventPublisherAware{
private ApplicationEventPublisher
publisher;
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher){
this.publisher = applicationEventPublisher;
}
public void publishEvent(ApplicationEvent event ) {
this.publisher.publishEvent(event);
}
}
Now in our Business Logic Service class, we have freed it from any direct dependence on Spring framework.
package com.test4;
public class Service {
private MyAppEvent event;
private MyAppEventPublisher
publisher;
public void setEvent(MyAppEvent event) {
this.event = event;
}
public void setPublisher(MyAppEventPublisher publisher) {
this.publisher = publisher;
}
public void service(){
this.publisher.publishEvent(this.event);
}
}
Using Spring XML configuration we will inject the properties MyAppevent and MyAppEventPublisher to the Service class
<?xml version="1.0"
encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="ServiceBean" class="com.test4.Service">
<property name="event">
<ref bean="OfferEventBean" />
</property>
<property name="publisher">
<ref bean="MyAppEventPublisherBean" />
</property>
</bean>
<bean id="OfferEventBean" class="com.test4.OfferEvent">
<constructor-arg>
<ref bean="ServiceBean" />
</constructor-arg>
</bean>
<bean class="com.test4.OfferEventListener" />
<bean id="MyAppEventPublisherBean"
class="com.test4.MyAppEventPublisher"/>
</beans>
No comments:
Post a Comment