Reading Notes for Spring 3 Core Components Tutorial Part I Part IV (Chapter 17 to Chapter 19)

  |   Source

This post is transferred from my old Hexo blog site, created on 2014.

This is a reading note from Spring Framework 3.1 Tutorial pdf, created by tutorialspoint. This pdf contains information for Spring 3 Core Basics, which is very useful for understanding defination and practive in Spring programming.

This note includes Chapter 17 to Chapter 19 in tutorial.

Chapter 17: Event Handling in Spring

In Spring, the ApplicatonContext publishes certain types of events when loading the beans.

ApplicationEvent class and ApplicationListener interface is used in ApplicationContext to deal with event handling.

If a bean implements ApplicationListener, then every time ApplicatioContext publish an ApplicationEvent, this bean will be notified.

Spring Events are following: images/posts/spring_events.png

Spring event handling is single-threaded. So if an event is published, unless all receivers get the message, the processes are blocked and the flow will not continue.

A bean can implement the ApplicationListener interface to listen a event. ApplicationListener only has one method, which is onApplicationEvent().

Example:

XML:

<bean id="helloWorld" class="com.sample.HelloWorld">
    <property name="message" value="Hello World!"/>
</bean>
<bean id="cStartEventHandler" class="com.sample.CStartEventHandler" />
<bean id="cStopEventHandler" class="com.sample.CStopEventHandler"/>

JAVA:

public class HelloWorld{
        private String message;
        //Assume we give message a setter and getter
}
//This is a listener we defined for start an event. So we implements ContextStartedEvent
public class CStartEventHandler implements ApplicationListener<ContextStartedEvent>{
    public void onApplicationContext(ContextStartedEvent event){
        System.out.println("ContextStartedEvent Received");
    }
}
//This is a listener we defined for stop an event. So we implements ContextStoppedEvent
public class CStopEventHandler implements ApplicationListener<ContextStoppedEvent>{
    public void onApplicationContext(ContextStartedEvent event){
        System.out.println("ContextStoppedEvent Received");
    }
}
public class Test{
    public static void main(String[] args){
        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //Start a event
        context.start();

        HelloWorld obj = (HelloWorld) context.getBean("helloWorld");

        obj.getMessage();

        //Stop an event
        context.stop();
    }
}

Chapter 18: Custom Events in Spring**

To create a custom event, you need a event class, a event publisher class and a event handler class:

XML: :::xml

JAVA:

//To create a custom event, event class needs to extend ApplicationEvent
public class CustomEvent extends ApplicationContext{
    public CustomEvent(Object source){
        super(source);
    }
    public String toString(){
    return "Custom Event";
    }
}
//To create a custom event publisher, publisher class needs to implement ApplicationEventPublisherAware
public class CustomEventPublisher implements ApplicationEventPublisherAware{
    private ApplicationEventPublisher publisher;

    public void setApplicationEventPublisher(ApplicationEventPublisher publisher){
        this.publisher = publisher;
    }
    public void publish(){
        ConstomEvent ce = new CustomEvent(this);
        publisher.publishEvent(ce);
    }
}
//To create a custom event handler, handler class needs to implement ApplicationListener<CustomEvent>
public class CustomEventHandler implements ApplicationListener(CustomEvent){
    public void onApplicationEvent(CustomEvent event){
        System.out.println(event.toString());
    }
}
//...
ConfiguraableApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

CustomEventPublisher cvp = (CustomEventPublisher) context.getBean("customEventPublisher");
cvp.publish(); //My Custom Event
cvp.publish(); //My Custom Event

Chapter 19: AOP with Spring Framework

Aspect Oriented Programming (AOP) entails breaking down program logic into distinct parts called concerns,or crossing-cutting concerns. These concerns are conceptually separate from the application's bussiness logic.

Spring AOP modules provides interceptors to intercept an application. For example. when a method is executed, you can add extra functionality before or after the method execution.

AOP Terminologies images/posts/AOP_Term1.png images/posts/AOP_Term2.png

Type of Advice images/posts/AOP_Advice.png

XML Schema Based Aspect Implementation

Use regular classes along with xml based configuration

xml needs to be configured:

<beans xmlns="..."
       xmlns:aop="..."
       xmlns:schemaLocation="...">
</bean>

You need to add AspectJ libraries to your CLASSPATH.

The way to declare an aspect is using <aop:aspect> element and usint ref attribute to find bean:

<aop:config>
    <aop:aspect id="testAspect" ref="testBean">
    ...
    </aop:aspect>
</aop:config>

<bean id="testBean" class="...">
</bean>

The way to declare an pointcut is to use <aop:pointcut> elements. pointcut is sued to determine the method(i.e. join point) to be excuted in advices:

<aop:config>
    <aop:aspect id="testAspect" ref="testBean">
        <aop:pointcut id="testAttribute" expression="execution(* com.xyz.Classes.*.*(...))"/>
        <!--We use regular expression to make sure all classes under com.xyz.Classes package have a "testAttribute" attribute. This attribute can carry advices-->

        <aop:pointcut id="testArribute2" express="executon(* com.sample.Test.getName(...))"/>
        <!--This means the method getName() in com.sample.Test class has a pointcut called testAttribute2-->
    </aop:aspect>
</aop:config>

<bean id="testBean" class="...">
</bean>

The way to declare an advice is to add five advices inside an <aop:aspect> element, using <aop:{ADVICE Name}> element:

<aop:config>
    <aop:aspect id="testAspect" ref="testBean">
        <aop:pointcut id="testAttribute" expression="execution(* com.sample.test.*.*(...))"/>

        <aop:before pointcut-ref="testAttribute" method="task"/>
        <aop:after pointcut-ref="testAttribute" method="task"/>
        <aop:around pointcut-ref="testAttribute" method="task"/>

        <aop:after-returning returning="retVal" pointcut-ref="testAttribute" method="task"/><!--method must hava papameter named retVal-->
        <aop:after-throwing throwing="ex" pointcut-ref="testAttribute" method="task"/><!--method must hava papameter named ex-->
    </aop:aspect>
</aop:config>

<bean id="testBean" class="...">
</bean>

Example:

XML:

<beans xmlns="..."
       xmlns:aop="..."
       xmlns:schemaLocation="..."
>
    <aop:config>
        <aop:aspect id="log" ref="logging"> <!--Spring will find a bean with id logging for aspect class-->
            <aop:pointcut id="selectAll" expression="execution(* com.sample.setName(...))"/>
            <!--Here we define advices trriger for method setName() -->
            <aop:before pointcut-ref="selectAll" method="beforeAdvice"/>
            <aop:after pointcut-ref="selectAll" method="afterAdvice"/>
            <aop:after-returning pointcut-ref="selectAll" returning="retVal" method="afterReturingAdvice"/>
            <aop:after-throwing pointcut-ref="selectAll" throwing="ex" method="AfterThrowingAdvice"/>
        </aop:aspect>
    </aop:config>

    <bean id="student" class="com.sample.Student">
        <property name="name" value="Tim"/>
        <property name="age" value="11"/>
    </bean>

    <bean id="logging" class="com.sample.Logging"/>
</beans>

JAVA:

public class Logging{
    //Execute before a selected method execution
    public void beforeAdvice(){
        System.out.println("Before Execution");
    }
    //Execute after a selected method execution
    public void afterAdvice(){
        System.out.println("After Execution");
    }
    //Execute when any method returns
    public void afterReturningAdvice(Object retVal){
        System.out.println("Returning Execution");
    }
    //Execute if there is any exception raised
    public void AfterThrowingAdvice(IllegalArgumentException ex){
        System.out.println("Exception Execution");
    }
}
public class Student{
    private Integer age;
    private String name;
    //Assume we have getter and setter for them with message print out

    public void printThrowException(){
        System.out.println("Exception raise") throw new IllegalArgumentException();
    }
}
public class Test{
    public static void main(String[] args){
        ApplicationContext context = new ClassPathApplicationContext("beans.xml");
        Student student = (Student) context.getBean("student");

        student.getName();
        student.setName("Ann");
        student.printThrowException();
    }
}

//Output:
//Tim
//Before Execution
//Returning Execution
//After Execution
//Exception Execution

@AspectJ Based AOP with Spring

@AspectJ refers a style of declaring aspects as regular Java classes with Java 5 annotations.

You need to add <aop:aspectj-autoproxy> in xml file first.

You also need AspectJ libraries in your CLASSPATH

To declaring an aspect, you add @Aspect above the class name.

To declaring an pointcut, you need to declar two parts:

A pointcut expression using @Pointcut

A pointcut signature, which is a method without implementation. The name of the method is like the id of pointcut in xml file above:

@Pointcut("execution(*com.sample.*.*(...))") //Pointcut expression, telling Spring the place to exectue advices
private void testAttribute(); //Pointcut Signature

To declaring advice, using @{advice_name} annotations:

@Before("testAttribute()") //pointcut expression. We use method here
public void doBeforeTask(){...}

@Before("testAttribute()")
public void doAfterTask(){...}

@Around("testAttribute()")
public void doAroundTask(){...}

@AfterReturning(pointcut="testAttribute()",returning="retVal")
public void doAfterReturnningTask(Object retVal){...}

@AfterThrowing(pointcut="testAttribute()",throwing="ex")
public void doAfterThrowingTask(Exception ex){...}

Example:

XML: :::xml

<!--Assume we have Student bean the same as example above-->
<!--Assume we have Logging bean the same as example above-->

JAVA:

@Aspect
public class Logging{
    @Pointcut("exectution(*com.sample.Student.setName(...))")
    private void selectAll();   //If we use xml, this is defined in xml file. Now we move it to jave

    @Before(selectAll())
    public void beforeAdvice(){
        //same as last example
    }
    @After(selectAll())
    public void afterAdvice(){
        //same as last example
    }
    @AfterReturning(pointcut="selectAll()", returning="retVal")
    public void afterReturningAdvice(Object retVal){
        //same as last example
    }
    @AfterThrowing(pointcut="selectAll()" throwing="ex")
    public void AfterThrowingAdvice(IllegalArgumentException ex){
        //same as last example
    }
}

//If we run Test.java from last example, we should get same results.
Comments powered by Disqus