Friday, 25 March 2011

Spring 3.0 with EL

Spring 3.0 introduces support for expression language, which is similar to Unified EL support in jsp. The intention was to further provide different ways of setting bean properties.
The advantage of EL is that it can support different kinds of expressions like Boolean, literal ,regular , method invocation, etc.

It is also called spEL or spring EL.
Now again there are 2 methods of using EL notation - xml and annotations.

Example :
public class ErrorHandler {

private String defaultLocale;

public void setDefaultLocale(String defaultLocale) {
this.defaultLocale = defaultLocale;
}

public void handleError() {
//some error handling here which is locale specific
System.out.println(defaultLocale);
}
}

Using EL in xml  config :

<bean id="errorHandler" class="xxxx.ErrorHandler">
<property name="defaultLocate" value="#{systemProperties['user.region']}" />
</bean>

Annotation style config:

import org.springframework.beans.factory.annotation.Value;

public class ErrorHandler {

@Value("#{ systemProperties['user.region'] }")
private String defaultLocale;

public void handleError() {
//some error handling here which is locale specific
System.out.println(defaultLocale);
}
}
Prior to Spring 3.0 , the only way to provide configuration metadata was XML.

Monday, 21 March 2011

Generating java classes from xsd (Eclipse) : Jaxb


  1. Create a java project in eclipse
  2. Create a xsd file: (Copy xsd file from here )
  3. Run xjc command in command prompt.
    Go to the project folder having this xsd. Note that eclipse has src folder....we have to generate packages here.
    run the following command here


  4. Now go to eclipse and these java classes to the project and we are done.

Sunday, 20 March 2011

Spring : Different ways of DI


There can be multiple ways of doing dependency injections, like :

Spring : Life Cycle of bean

Beans are managed by IOC container, having a life cycle associated with it. These are the possible ways of managing there life cycle:

  • Callback API implementation
  • XML configuration
  • Annotations

There are two distinct spring containers one is bean factory and another is application context. Life cycle phases varies a lil in the containers. More precisely, only one additional phase is added in case of application context. Let's see what these phases are:

  1. Instantiate: in this phase container finds the bean's definition and default constructor called.
  2. Autowiring executes
  3. Dependency check performed
  4. setters method of bean called
  5. setBeanFactory () / setApplicationContext () / method called
  6. afterPropertiesSet() / init-method /@PostConstruct method called
  7. Application running, beans ready to work
  8. destroy()/ destroy-method / @PreDestroy method called
    An existing bean can be removed from the container in two ways:
    1. DisposableBean: If bean implements the DisposableBean interface then destroy() method is called.
    2. Call-custom destroy: if custom-destroy method is specified then it is called.

Implementing the life cycle interface

Spring : Creating custom scopes

Using Load time weaving instead of proxies

Load time weaving or LTW can be achieved from spring 2.5.0.

Performance wise, LTW is better because separate proxy object is not created.

Spring Index

Introduction to Spring

IOC or DI in Spring

  1. Annotation approach for DI
    In this approach we place @Resource on the property or setters of the class. Little cleaner than xml file, because managing long xml files is not easy for humans.
    Annotation approach for DI
    Annotation approach for constructor injection
  2. Other cases of DI
    a)
    Spring : Inheritance between beans
    b) Factory methods helps us to write classes with factory design pattern.
    ---Spring : factory-method
    ---Spring : Factory methods with parameters
    ---Spring : Creating custom factory-bean
    c) Lookup method injection
    ---Spring : Lookup Method injection
  3. Lazy initialization of beans
    Earlier we discussed lookup method injection. Now we can discuss about lazy initialization, and alternative approach to lookup method injection.
    Spring : ApplicationContextAware Interface
    Spring : ObjectFactory Interface
    Spring : ServiceLocatorFactoryBean Interface
  4. Spring : PropertyOverrideConfigurer
  5. Other cases of DI (examples)
    Can an Innerclass be instantiated in Spring?
    Spring Map ExampleSpring List Property Example
  6. Spring 3.0 EL support
  7. Lifecycle of beans
    Spring : BeanNameAware Interface
    Spring : init-method and destroy-method
    Spring : BeanPostProcessor interface 
    Spring : BeanFactroyPostProcessor interface
    Spring : Lifecycle interface
    Spring : DisposableBean Interface and Initializing...
    @PostConstruct and @PreDestroy example 
    @Required annotation

 

AOP

Need for AOP
Introduction to AOP
Spring AOP vs AspectJ
AOP support in spring
Advices would have been explained in above mentioned points. So we can talk about them now.
Advice types in spring
Terminology of AOP ( though some part covered in above points)
Writing the Aspect class
Using xml style configuration
Using annotation style configuration
About joinpoint object
Pointcut expressions
Binding parameters to advice
Named pointcuts
Implementing After and AfterReturning Advice
Exception handling using AOP
Implementing Around Advice in aop
Pitfalls of AOP

Spring : DisposableBean Interface and InitializingBean

The InitializingBean and DisposableBean are two marker interfaces which call the  afterPropertiesSet() for the begining and destroy() for the last action of initialization and    destruction to be performed.

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class StudentService implements InitializingBean, DisposableBean {
String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public void afterPropertiesSet() throws Exception {
System.out.println(" After properties has been set : " + message);
}

public void destroy() throws Exception {
System.out.println("Cleaned everything!!");
}

}


In context.xml bean is created in usual style.

Spring List Property Example

The Spring Framework has bean support for the Collections. It provide list, set, map and props elements. Here in this tutorial you will see about the list elements which is used to set values inside the list.

Example

Consider this list bean :

import java.util.List;

public class CollegeBean {
private List<Object> lists;

public List<Object> getLists() {
return lists;
}

public void setLists(List<Object> lists) {
this.lists = lists;
}

@Override
public String toString() {
return "College [lists=" + lists + "]";
}
}


Simplebean


public class StudentBean {
private String name;
private String address;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

@Override
public String toString() {
return "Student [address=" + address + ", name=" + name + "]";
}
}


context.xml


<!-- Spring List Property Example  -->

<bean id="studentBean" class="com.xxx.StudentBean">
<property name="name" value="satya" />
<property name="address" value="Delhi" />
</bean>

<bean id="collegeBean" class="com.xxx.CollegeBean">

<property name="lists">
<list>
<value>1</value>
<ref bean="studentBean" />
<bean class="com.xxx.StudentBean">
<property name="name" value="ankit" />
<property name="address" value="delhi" />
</bean>
</list>
</property>
</bean>

<!-- End -->

Spring : Lifecycle interface

Lifecycle interface is basically meant for managing startup and shutdown callbacks. For eg., on startup we would like to load data into the cache and on shutdown just clear the cache or start the process at startup and end it when exiting.

So SmartLifecycle is extension of Lifecycle Interface.

Example :

import org.springframework.context.SmartLifecycle;

public class LifecycleImpl implements SmartLifecycle {

public LifecycleImpl() {
System.out.println("LifecycleImpl class instantiated..");
}

@Override
public boolean isAutoStartup() {
System.out.println("isAutoStartup method our LifecyleImpl class called..");
return true;
}

@Override
public void stop(Runnable r) {
System.out.println("stop(Runnable) method of our LifecycleImpl class called..");
r.run();
}

@Override
public boolean isRunning() {
System.out.println("isRunning method of our LifecycleImpl class called..");
return true;
}

@Override
public void start() {
System.out.println("start method of our LifecycleImpl class called..");
}

@Override
public void stop() {
System.out.println("stop method of our LifecycleImpl class called..");
}

@Override
public int getPhase() {
System.out.println("getPhase method of our LifecycleImpl class called..");
return 1;
}
}



Create the bean in simple way in context.xml.

Spring Map Example

In this example you will see how bean is prepared for injecting Map collection type key and its values.

import java.util.Iterator;
import java.util.Map;

public class MapBean {
private Map<String, Integer> student;
public void setDetails(Map<String, Integer> student) {
this.student = student;
}
public void showDetails() {
Iterator it = student.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println(pairs.getKey() + " = " + pairs.getValue());
}
}
}


In the config file :


<bean id="mapbean" class="com.xxxx.MapBean">
<property name="details">
<map>
<entry key="Satya" value="101"/>
<entry key="Rohit" value="102"/>
<entry key="Aniket" value="103"/>
</map>
</property>
</bean>

BeanFactoryPostProcessor interface

The semantics of this interface is similar to BeanPostProcessor but with one major difference : BeanFactoryPostProcessor operate on bean configuration metadata; So spring IoC container allow BeanFactoryPostProcessor to read the configuration metadata and potentially change it before the container instantiates any bean other than BeanFactoryPostProcessor .

But if you want to change the actual bean instances( the objects that are created from the configuration metadata), then use BeanPostProcessor.

Example …

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class BeanFactoryPostProcessorImpl implements BeanFactoryPostProcessor {

public BeanFactoryPostProcessorImpl() {
System.out.println("BeanFactoryPostProcessorImpl class instantiated..");
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory)
throws BeansException {
System.out.println("postProcessBeanFactory method of our BeanFactoryPostProcessorImpl class called..");

//dynamically registering a new bean in the context. you can try this later on.
//similar to @Configuration and @Bean we saw in previous section.
//factory.registerSingleton("myBean", new SampleBean());
}
}



Again one of the commonly used BeanFactoryPostProcessor is PropertyPlaceHolderConfigurer class. We already have seen the usage of this class before. This replaces the config of any bean containing ${}  with the actual property value so by the time the bean is instantiated, the correct values are already in the container.

@Required annotation

BeanPostProcessor is used by the framework heavily. One of the best example is RequiredAnnotationBeanPostProcessor class. In spring we require @Required annotation to make it a mandatory dependency, that thas to be injected.

Just by using annotation in the code will not work, since someone has to check whether the requirement has been met or not and reposrt an error it not.

Example

//The service
public interface BankService {

public BillPaymentService getBillPaymentService();
public CustomerService getCustomerService();
}

//The impl class
public class BankServiceImpl implements BankService {

private CustomerService customerService;
private BillPaymentService billPaymentService;

@Required
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}

@Required
public void setBillPaymentService(BillPaymentService billPaymentService) {
this.billPaymentService = billPaymentService;
}

public BillPaymentService getBillPaymentService() {
return billPaymentService;
}

public CustomerService getCustomerService() {
return customerService;
}
}


Now here we have mentioned what is required, but we need RequiredAnnotationBeanPostProcessor to check whether these required dependency are injected or not.


The configuration


<!--  According the code, we need to set both the dependencies.
Comment out one or both the property tag and see the error -->
<bean id="bankService" class="com.xxxx.BankServiceImpl">
<property name="billPaymentService" ref="billPaymentService" />
<property name="customerService" ref="customerService" />
</bean>

<!-- Just by using @Required will not work. Someone has to parse it
and that's the role of this class -->
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />


Spring : BeanPostProcessor interface

The interface BeanPostProcessor allows custom modification of all new bean instance like for example making for marker interfaces or wrapping them with all proxies. The advance of interface BeanPostProcessor is that it auto-detect BeanPostProcessor beans in their bean definations and apply all beans before any others get created.

So it provides callback methods thaty you can implement to provide your own instantiation logic, dependency resolution logic and so forth. In a way you override default container's logic.

You can control the order in which these BeanPostProcessor interfaces execute by setting the order property only if the BeanPostProcessor implements the Ordered Interface.

Classes which implement BeanPostProcessor are special and treaded differently by container. All BeanPostProcessor and their directly referenced beans are instantiated on startup, as a part of the special startup phase of the ApplicationContext.

Example:

 

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

class StudentBean implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {

System.out.println("Before initialization : " + beanName);


return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {

System.out.println("After initialization : " + beanName);
return bean;
}
}



So BeanPostProcessor implementation gives us chance to perform custom processing before and after any bean is initialized.


In config.xml


<bean id="studentBean" class="com.roseindia.common.StudentBean" />

@PostConstruct and @PreDestroy example

In this tutorial you will learn how to implement the @PostConstruct and @PreDestroy which work similar to init-method and destroy-method in bean configuration file or implement the InitializingBean and DisposableBean in your bean class. To use @PostConstruct and @PreDestroy you have to register the CommonAnnotationBeanPostProcessor at bean configuration or specifying the <context:annotation-config /> in the bean configuration file.

Consider the service bean:

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class StudentService {

String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

@PostConstruct
public void initIt() throws Exception {
System.out.println("After properties has been set : " + message);
}

@PreDestroy
public void cleanUp() throws Exception {
System.out.println("Cleaned Everyting");
}

}


Bean config file:


<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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
>

<context:annotation-config />

<bean id="studentService" class="com.xxxx.StudentService">
<property name="message" value="property message" />
</bean>

</beans>


Pitfalls with aspect technologies

Even though aspect technologies are very powerful. Especially to address cross-cutting concerns like transactions, it shouldn’t be used everywhere it’s possible.

The first part of this post consists of a simple example that uses AspectJ to return an unexpected value. The last part is about where aspects fits and where you should consider to avoid it.

A quote from the Spider-Man movie:

With great power comes great responsibility

This applies to some degree to aspect technologies too. Since it can change the behaviour of an application at compilation, startup or at runtime. Even without leaving a trace in the source code.

Spring : init-method and destroy-method

In this first example, I’ll show you how the lifecycle of a bean happens within the xml-configfile.

In the xml-file, we can define an init- and destroy-method to the bean, which will be called automatically by Spring.
Config.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"
>
<!-- -->
<bean id="attributesTest" class="a.Test" init-method="initMethod"
destroy-method="destroyMethod">
</bean>

</beans>

 

Now consider our bean with these 2 methods into it:

 

public class LifeCycledBean2{    
//
public LifeCycledBean2(){
System.out.println("We are in the constructor of LifeCycledBean2");
}
public void initMethod()
{
System.out.println("We are in initMethod of LifeCycledBean2");
}
public void destroyMethod()
{
System.out.println("We are in destroyMethod of Test");
}
}




Main or Runner program
In this case, I’ll use AbstractApplicationContext because this Context has a function to destroy the Context which a normal ApplicationContext doesn’t have.

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class JustATest {
public static void main(String[] args) {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("Config.xml");
ctx.registerShutdownHook();
Test test = ctx.getBean("attributesTest",Test.class);
}
}


The output will be:

We are in the constructor of Test
We are in initMethod of Test
We are in destroyMethod of Test

It’s also possible to declare default init- and destroy-methods in the xml-file. This is done in the beans-tag:

<?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"

default-init-method="initMethod"
default-destroy-method="destroyMethod"
>
...

Saturday, 19 March 2011

Spring : BeanNameAware Interface

Consider the following bean:

import org.springframework.beans.factory.BeanNameAware;

public class LifeCycledBean implements BeanNameAware
{
private String languageName;
private String beanName;

public LifeCycledBean ()
{
}

public String getLanguageName()
{
return languageName;
}

public void setLanguageName(String languageName)
{
this.languageName = languageName;
}

@Override
public void setBeanName(String beanName)
{
this.beanName = beanName;
}

public String getBeanName()
{
return beanName;
}
}


The above sample class provides one such implementation and the below client code uses the above class to know the name of the bean.

static void beanNameAwareTest()
{
Resource resource = new FileSystemResource("./src/resources/bean-lifecycle-1.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
LanguageBean lifeCycledBean= (LanguageBean)beanFactory.getBean("lifeCycledBean");
System.out.println(lifeCycledBean.getLanguageName());
System.out.println(lifeCycledBean.getBeanName());
}



The following piece of Xml code snippet goes into the Xml Configuration file.

<bean id="javaLanguage" class="com.xxxx.LifeCycledBean">
<property name="lifeCycledBean" value="Java"/>
</bean>

Implementing @Around advice

To get pre and post processing of calling any function, its good to implement @Around advice.

Consider the following Aspect with around advice:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.util.StopWatch;

@Aspect
public class ProfilingAspect {

@Around("execution(* *(..))")
public Object profile(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch watch = new StopWatch();
watch.start(joinPoint.getSignature().getName());
try {
return joinPoint.proceed(); //calling the target method
}
catch(Exception e) {
throw e;
}
finally {
watch.stop();
System.out.println(watch.prettyPrint());
}
}
}

 

Corresponding config file:



<aop:aspectj-autoproxy />

<bean id="profilingAspect" class="ex7.ProfilingAspect" />
<!--some service class -->
<bean id="customerService" class="service.CustomerServiceImpl" />

Exception handling with AOP

The throws advice is executed when a method throws an exception.

Handling exception by this method saves us from writing repeating try-catch block again and again.

Consider the following java code:

//interface with method throwing exception
public interface BusinessInterface {

public void someBusinessMethod() throws BusinessException;

}
//class implementing it
import org.springframework.jdbc.BadSqlGrammarException;

public class BusinessComponent implements BusinessInterface {

public void someBusinessMethod() throws BusinessException {
//we are raising a different exception to see the aspect coming into action
//assume that you are connecting to the database and something goes wrong
throw new BadSqlGrammarException("","",null);
}
}


So now this business logic may throw exception, and it will be handled by Aspect.


So we have to write handler for this:


import java.util.Locale;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;

@Aspect
public class ExceptionHandler implements MessageSourceAware {

private MessageSource messageSource;

@Override
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}

@AfterThrowing(pointcut="execution(* someBusinessMethod(..))", throwing="ex")
public void handleException(JoinPoint jp, RuntimeException ex) throws Throwable {
System.out.println("Routine exception handling code here.");
System.out.println("Let's see who has raised an exception!");
System.out.println("===================================");
System.out.println(jp.getSignature().getName());
System.out.println("===================================");
throw new BusinessException(messageSource.getMessage(jp.getSignature().getName(), null, Locale.getDefault()));
}
}


Now if we want pre and post analysis of method, @Around advice will be handy for this.


Corresponding config file:



<aop:aspectj-autoproxy />

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="ex6/messages" />
</bean>

<bean id="exceptionHandler" class="com.xxxx.ExceptionHandler" />

<bean id="businessComponent" class="com.xxxx.BusinessComponent" />

Implementing @After and @AfterReturning advice

As we have done @Before, till now, it is also similar to that.

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class LoggingAspect {

@After("bean(*Service)")
public void log(JoinPoint joinPoint) {
System.out.println("log advice got executed after call to method : "+joinPoint.getSignature().getName());
}

@AfterReturning(pointcut="execution(* balance(..)) && args(acno)", returning="balance")
public void validate(JoinPoint joinPoint, long acno, double balance) {
System.out.println("validate advice called after successful return from balance method");
System.out.println("acno passed was "+acno+" and the balance returned was "+balance);
}
}



Spring config file :


<aop:aspectj-autoproxy />

<bean id="loggingAspect" class="ex5.LoggingAspect" />

<bean id="orderService" class="service.OrderServiceImpl" />

<bean id="customerService" class="service.CustomerServiceImpl" />

Named pointcut expression

Sometimes it happens that we may need same pointcut at multiple places. But since pointcut expressions are lengthy, it will be good if instead of repeating we can give a logical name to that pointcut and refer to it by logical name.

So for this we have to first create pointcut config :

package com.xxxx;
//
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class PointcutConfig {

@Pointcut("execution(public * service.*.*(..))") //This is a pointcut expression
public void serviceComponents() {} //This is a name given to the pointcut expression

@Pointcut("execution(* apply*(..))")
public void applyMethods() {}

}



Note that we @Aspect and @Pointcut annotations above.


When we write our own aspect we can simply refer to these method names in pointcut-config now:


import java.util.Date;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LoggingAspect {

@Before("com.xxxx.PointcutConfig.applyMethods()")
public void log(JoinPoint joinPoint) {
System.out.println("log advice executed for method : "+joinPoint.getSignature().getName());
}

@Before("com.xxxx.PointcutConfig.serviceComponents()")
public void timeLog(JoinPoint joinPoint) {
System.out.println("request for method : "+joinPoint.getSignature().getName()+" occurred at "+new Date());
}
}


In the config file, we have to define both beans:


<aop:aspectj-autoproxy />

<bean id="pointcutConfig" class="ex4.PointcutConfig" />

<bean id="loggingAspect" class="ex4.LoggingAspect" />

<bean class="service.OrderServiceImpl" />

<bean class="service.CustomerServiceImpl" />

Binding parameters to advice

A joinpoint object provides all the details required by the advice to perform any kind of operation.

Suppose we have to validate an order, and so we are writing our own aspect to get argument from pointcut - expression and perform validation. Example:

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import service.Order;

@Aspect
public class OrderValidator {

@Before("execution(* placeOrder(..)) && args(order)")
public void validateOrder(Order order) {
//some order validation logic here
System.out.println("Just checking it out!");
}
}

In the config file we write:


<aop:aspectj-autoproxy />

<bean class="ex3.OrderValidator" />

<bean class="service.OrderServiceImpl" />


Pointcut expression

The most typical pointcut expressions are used to match a number of methods by their signatures. A common method based pointcut expression is something like

PCD(<method scope> <return type> <fully qualified class name>.*(arguments))


  1. PCD - PCD is pointcut designators. Spring AOP supports following pointcut expression -
    -- execution, with, this,target, args
    --Spring AOP also supports an addition PCD - "bean"
    --Of these, execution is most common
  2. method scope: Advice will be applied to all the methods having this scope. For e.g., public, private, etc. Please note that Spring AOP only supports advising public methods.
  3. return type: Advice will be applied to all the methods having this return type.
  4. fully qualified class name: Advice will be applied to all the methods of this type. If the class and advice are in the same package then package name is not required
  5. arguments: You can also filter the method names based on the types. Two dots(..) means any number and type of parameters.

Also these expressions can be chained to create composite pointcuts : && (and), || (or) , ! (not)


Some examples


the execution of any public method:
execution(public * *(..))

the execution of any method with a name beginning with “set”:
execution(* set*(..))

the execution of any method defined by the MyService interface
execution(* com.xyz.service.MyService.*(..))

the execution of any method defined in the service package:
execution(* com.xyz.service.*.*(..))

the execution of any method defined in the service package or a sub-package:
execution(* com.xyz.service..*.*(..))

any join point (method execution only in Spring AOP) WITHIN the service package:
within(com.xyz.service.*)

any join point (method execution only in Spring AOP) within the service package or a sub-package:
within(com.xyz.service..*)

any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface:
this(com.xyz.service.AccountService)

any join point (method execution only in Spring AOP) where the target object implements the AccountService interface:
target(com.xyz.service.AccountService)

any join point (method execution only in Spring AOP) which takes a single parameter, and where the argument passed at runtime is Serializable:
args(java.io.Serializable)

Spring : Advice and its type

Any functionality that exists in an application, but cannot be added in a desirable way is called a cross-cutting concern.

That cross-cutting concern is called aspect-oriented programming (AOP). It deals with the functionality in applications that cannot be efficiently implemented with pure object-oriented techniques.

One of the core features of AOP frameworks is implementing cross-cutting concerns once and reusing them in different places and in different applications. In AOP jargon, the implementation of a cross-cutting concern is called an advice.

AOP frameworks allow you to define which advice is applied to which methods

Spring AOP supports following types of advices
Joinpoint is the point of execution of application, like method.
Spring AOP supports four advice types that each represents a specific scenario for advice implementations:
  • Around advice: Controls the execution of a join point. This type is ideal for advice that needs to control the execution of the method on the target object.
  • Before advice: Is executed before the execution of a join point. This type is ideal for advice that needs to performan action before the execution of the method on the target object.
  • After advice: Is executed after the execution of a join point. This type is ideal for advice that needs to perform an action after the execution of the method on the target object.
  • Throws advice: Is executed after the execution of a join point if an exception is thrown. This type is ideal for advice that needs to performan action when the execution of the method on the target object has thrown an exception.

Using annotation for configuring advices

We again take example of before advice.

Now we add @Aspect at the bean level. But on the method of the Aspect class, we can have annotations depending on what type of method or better advice they are. For before type advice we have @Before annotation.

Creating the aspect class


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LoggingAspect {

//TODO: Try other pointcut expressions also as mentioned in slide no. 203-207
@Before("execution(public * apply*(..))")
public void log(JoinPoint joinPoint) {
System.out.println("common logging code executed for : "+joinPoint);
}
}


Now the bean class is quite cleaner, as we are annotation:


<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
>

<aop:aspectj-autoproxy />

<bean id="customerService" class="service.CustomerServiceImpl" />

<bean id="loggingAspect" class="ex2.LoggingAspect" />

</beans>


Here we are simply logging a simple text before entering the methods. Consider the case when we want to print about arguments.


This is where JoinPoint object comes into picture.


More about JoinPoint Object


Changing the before advice to take care of arguments , etc of the methods.


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class LoggingAspect2 {

@Before("execution(public * apply*(..))")
public void log(JoinPoint joinPoint) {
Object proxyObject = joinPoint.getThis();
Object targetBean = joinPoint.getTarget();
Object[] args = joinPoint.getArgs();
Signature signature = joinPoint.getSignature();
//some logging code here
}
}



In the above xml file just change the class name of LoggingAspect to LoggingAspect2.


As the names of the method suggest :



  • this : The current executing object that has been intercepted

  • target : The target of the execution (typically our object)

  • args -  method args

  • signature - method signation of the joinpoint

One of the reason why aspectJ was adopted by the spring was because of v.powerful and easy to learn pointcut expression, which define where our aspects will execute.

Spring : Xml style configuration for pointcuts (Before advice)

The Aspect Class:

import org.aspectj.lang.JoinPoint;

//This is an Aspect class
public class LoggingAspect {

//This is an advice.
//Pointcut means where will this advice be applied.
public void log(JoinPoint joinPoint) {
System.out.println("common logging code executed for : "+joinPoint);
}

}

The configuration file:

<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
>

<!-- Tells the container we will be using AspectJ.
Also tells the container to use the proxy approach for executing aspects -->
<aop:aspectj-autoproxy />

<bean id="customerService" class="service.CustomerServiceImpl" />

<bean id="loggingAspect" class="com.xxxx.LoggingAspect" />

<!-- Aop config start -->

<aop:config>
<aop:pointcut expression="execution(public * apply*(..))" id="pointcut1" />
<aop:aspect ref="loggingAspect">
<aop:before method="log" pointcut-ref="pointcut1" />
</aop:aspect>
</aop:config>

</beans>


Note that we are using "aop" namespace in the xml to configure it to aspect class.