Workshop 6
Workshop 6
Spring framework is developed on two core concept namely Dependency Injection and
Aspect Oriented Programming. AOP is a way of extending existing classes without
touching your existing code base which can be very useful under some circumstances.
AOP is just an interceptor to intercept some processes, for example, when a method is
execute, Spring AOP can hijack the executing method, and add extra functionality
before or after the method execution.
AOP provides the way to dynamically add the cross-cutting concern before, after or
around the actual logic using simple pluggable configurations. AOP is a tool for
implementing crosscutting concerns. AOP is most commonly used for applying
common concerns to many parts of an application in a large scale. Logging and security
are examples of cross cutting concerns.
Core Concept
Following terminologies are most commonly used while developing a program that uses
AOP.
1. Before Advice: These advices runs before the execution of join point methods. We
can use @Beforeannotation to mark an advice type as Before advice.
2. After (finally) Advice: An advice that gets executed after the join point method
finishes executing, whether normally or by throwing an exception. We can create
after advice using @After annotation.
3. After Returning Advice: Sometimes we want advice methods to execute only if the
join point method executes normally. We can use @AfterReturning annotation to
mark a method as after returning advice.
4. After Throwing Advice: This advice gets executed only when join point method
throws exception, we can use it to rollback the transaction declaratively. We
use @AfterThrowing annotation for this type of advice.
5. Around Advice: This is the most important and powerful advice. This advice
surrounds the join point method and we can also choose whether to execute the join
point method or not. We can write advice code that gets executed before and after
the execution of the join point method. It is the responsibility of around advice to
invoke the join point method and return values if the method is returning something.
We use @Around annotation to create around advice methods.
1. Pointcut which specifies joint point i.e. method where we implement business
logic
<aop:pointcut id="camerasnap" expression="execution(*
ch6.demo.aop.Camera.snap(..))" />
2. Aspect which implements advice method. In this, you specify reference to Aspect
class as well as pointcut reference.
Let us develop a sample application program that uses AOP concept based on
configurations stored on XML file.
try{
camera.validate(11);
}catch(Exception e){System.out.println(e);}
context.close();
return "main";
}
}
8. Create a file named appConfig.xml inside ch6.demo.controller package and put
following codes inside it.
<?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.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<aop:aspectj-autoproxy />
<bean id="camera" class="ch6.demo.aop.Camera"></bean>
<bean id="logger" class="ch6.demo.aop.Logger"></bean>
<aop:config>
<aop:pointcut id="pointCutAfterThrowing"
expression="execution(* ch6.demo.aop.Camera.validate(..))" />
<aop:pointcut id="camerasnap" expression="execution(*
ch6.demo.aop.Camera.snap(..))" />
<aop:pointcut id="logPointCut" expression="execution(public *
ch6.demo.aop.Camera.sayHello(..))" />
<aop:aspect id="loggeraspect" ref="logger" >
</aop:aspect>
</aop:config>
</beans>
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
<servlet>
<description></description>
<display-name>aopdispatcher</display-name>
<servlet-name>aopdispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-
class>
</servlet>
<servlet-mapping>
<servlet-name>aopdispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
12. Create main.jsp inside WebContent folder and put following codes
Analysis:
Let us develop a sample application program that uses AOP concept based on
annotation.The sample application is similar to the XML based application discussed
above.
6. Put following codes inside Logger.java [ This class is called Aspect class where
we implement advice method]
.
package ch6.demo.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class Logger {
@Pointcut("execution(* ch6.demo.aop.Camera.snap(..))")
public void cameraSnap() {
}
/*@Before("cameraSnap()")
public void aboutToTakePhoto() {
System.out.println("About to take photo...");
}
@After("cameraSnap()")
public void afterPhoto()
{
System.out.println("After Pointcut Demo");
}*/
@AfterThrowing( pointcut = "execution(*
ch6.demo.aop.Camera.validate(..))",throwing= "error")
public void myadvice1(JoinPoint jp,Throwable error)//it is advice
{
System.out.println("additional concern");
System.out.println("Method Signature: " + jp.getSignature());
System.out.println("Exception is: "+error);
System.out.println("end of after throwing advice...");
}
@AfterReturning(pointcut = "execution(public *
ch6.demo.aop.Camera.sayHello(..))", returning= "returnVal")
public void log(JoinPoint jp,String returnVal) throws Throwable
{
System.out.println("Return value:"+returnVal);
System.out.println("XML Configuration driven: After returning
"+jp.getSignature().getName()+"()");
}
@Around("cameraSnap()")
public Object myadvice(ProceedingJoinPoint pjp) throws Throwable
{
System.out.println("Additional Concern Before calling actual
method");
Object obj=pjp.proceed();
System.out.println("Additional Concern After calling actual method");
return obj;
}
}
7. Create a file named MyController.java inside ch6.demo.controller package and
put following codes inside it.
package ch6.demo.controller;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import ch6.demo.aop.Camera;
@Controller
public class MyController {
@RequestMapping(value="/",method=RequestMethod.GET)
public String displayMainPage()
{
ClassPathXmlApplicationContext context = new
ClassPathXmlApplicationContext("ch6/demo/controller/appConfig.xml");
Camera camera = (Camera)context.getBean("camera");
/*String result=camera.sayHello("Mukesh");
System.out.println("Return Value="+result);
camera.snap();*/
////////////////////////
try{
camera.validate(19);
}catch(Exception e){System.out.println(e);}
System.out.println("calling validate again...");
try{
camera.validate(11);
}catch(Exception e){System.out.println(e);}
context.close();
return "main";
}
}
8. Create a file named appConfig.xml inside ch6.demo.controller package and put
following codes inside it.
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<context:component-scan base-package="ch6.demo" />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
12. Create main.jsp inside WebContent folder and put following codes
Analysis:
Spring AOP:It is related to cross cutting concern.What it mean is in large system the
common functionality is scattered throughout different modules.so,aop provides a
easiest way to take out a common implementaiton in the form of aspect.The very base
principle of AOP is finding common tasks/aspects which returns in many places in the
code and dont belong to the concerete business of the code. For example write to log
on every entrance to any function, or when an object is created wrapp it, or send email
to admin when calling to specific function. So instead of the programmers will handle
these non businuss aspect we take it from them and we manage these aspects behond
the scene.
<aop:config>
<aop:pointcut id="pointCutAfterThrowing"
expression="execution(* ch6.demo.aop.Camera.validate(..))" />
<aop:pointcut id="camerasnap" expression="execution(*
ch6.demo.aop.Camera.snap(..))" />
<aop:pointcut id="logPointCut" expression="execution(public *
ch6.demo.aop.Camera.sayHello(..))" />
<aop:aspect id="loggeraspect" ref="logger" >
</aop:aspect>
</aop:config>
Reference:
1. http://stackoverflow.com/questions/2572158/what-is-aop-dependency-injection-
and-inversion-of-control-in-simple-english
2. http://www.tutorialspoint.com/spring/spring_ioc_containers.htm
Proxy Types
This is how you can force creation of the CGLIB proxies (set proxy-target-class="true"):
<aop:config proxy-target-class="true">
<!-- other beans defined here... -->
</aop:config>
When using AspectJ and its autopoxy support you can also force CGLIB proxies. This is
where the <aop:aspectj-autoproxy> is used and also here the "proxy-target-class" must
be set to true:
<aop:aspectj-autoproxy proxy-target-class="true"/>
JDK proxies work by implementing the same interface as your target object and
delegating calls to it; they do not work if there is no interface to implement. In case you
don't have an interface like above, Spring needs to use a byte code library like CGLIB to
dynamically create classes at runtime that incorporate the aspect functionality.
Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given
target object. (JDK dynamic proxies are preferred whenever you have a choice).
If the target object to be proxied implements at least one interface then a JDK dynamic
proxy will be used. All of the interfaces implemented by the target type will be proxied.
If the target object does not implement any interfaces then a CGLIB proxy will be used.
To enable CGLIB proxy, you have to declare following in your XML file:
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
Let us develop a sample application where we create proxy manually. For this, follow
the below steps:
1. Create a project named ProxyDemo1 and add following jar files into the project in
Java Build Path.
spring-core- spring-expression-
4.2.2.RELEASE.jar 4.2.2.RELEASE.jar
2. Create a package named ch6.demo.aop inside src folder and create following
various class files inside it.
3. PhotoSnapper.java which is an interface going to be inherited by target class
(Camera)
package ch6.demo.aop;
import org.springframework.stereotype.Component;
@Component("camera")
public class Camera implements PhotoSnapper,Machine{
public Camera() {
System.out.println("Constructor Code");
// TODO Auto-generated constructor stub
}
@Override
public void machineMethod() {
// TODO Auto-generated method stub
}
}
6. Logger.java an aspect class which comprises of advise methods
package ch6.demo.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Pointcut("execution(* ch6.demo.aop.Camera.snap())")
@Before("cameraSnap()")
package ch6.demo.aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
@Override
System.out.println("Hello ");
Object retVal=invocation.proceed();
System.out.print("!");
return retVal;
}
8. MyPointCut.java which comprises of creating pointcuts programmatically.
package ch6.demo.aop;
import java.lang.reflect.Method;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
if (targetMethod.equals(method.getName())) {
intercept = true;
return intercept;
9. beans.xml which comprises of codes for making proxy object as a target object
programmatically.
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:annotation-config></context:annotation-config>
<context:component-scan
base-package="ch6.demo.aop">
</context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-
autoproxy>
</beans>
10. TestApp.java which comprises of code to test various things like, programmatic
proxy creation, determining proxy types and so on.
package ch6.demo.aop;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
System.out.println("CGlib Proxy="+AopUtils.isCglibProxy(obj));
System.out.println("Dynamic
Proxy="+AopUtils.isJdkDynamicProxy(obj));
factory.addAdvisor(advisor);
factory.setTarget(obj1);
factory.addInterface(PhotoSnapper.class);
//factory.addAdvice(new MessageDecorator());
factory.setExposeProxy(true);
PhotoSnapper obj2=(PhotoSnapper)factory.getProxy();
try
camera.snap();
obj2.snap();
}
catch(Exception e)
System.out.println("Execption occuered="+e);
e.printStackTrace();
Analysis:
Your code never invokes the advice methods of an aspect class. Spring does it for you
based on your XML configuration or annotations on the aspect class. How does the
magic happen? Under the covers, Spring implements a proxy to intercept calls to a
target object.For cases in which interfaces are not available or not used in an
application’s design, it’s possible to create proxies by relying on CGLIB. To enable
CGLIB, you need to set the attribute proxy-targetclass= true in aop:aspectj-autoproxy.
Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxies for your
target objects.
One solution to above problem is that We can change the way the proxy system works
by changing the proxy to be an instance of target class. In order to do this, we should
have following tag on our container xml file. This is for annotation based approach.
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
proxy-target-class="true" will tell the system that the proxy object is an instance of target
class. If we do this, then proxy object along with target object (two objects) will be
created. Hence, if you have any constructor in target class, then due to proxy object
creation the constructor will be called first. As proxy class is child class of target class,
while calling constructor while creating proxy object, it will automatically call target class
constructor. It means, constructor will be called twice. To eliminate this problem, you
have to put all methods that the target class has in an interface and implement that
interface in a target class and will getting bean object, then cast it to this interface
object.
Reason is obj is sub class of Camera class and as Camera does not implement any
interface, proxy used is CGLIB not dynamic proxy.
However, if Camera class implements an interface lets us say PhotoSnapper, then you
will get following output:
If Camera class implements another interface let us say Machine, then you still will get
above output.
Note: Interfaces should not be empty
Hence, obj bean is not an instance of target class(Camera) rather it is an instance of all
interfaces that the target class implements.
try
{ camera.snap();
catch(Exception e)
{ System.out.println("Execption occuered="+e);
e.printStackTrace();
You will get above exception because bean retrieved is proxy and you are trying to
convert it into Camera
The solution to above problem is: We have to change the way how proxy works by
making sure that proxy be an instance of target class rather than an instance of
interfaces.
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
, then aop feature will not work and you will not get above error output, you will get
following output:
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
Now, the bean object is not an instance of proxy rather an instance of subclass of
Camera
Example:
TargetSource getTargetSource();
boolean getExposeProxy();
boolean getProxyTargetClass();
Advisor[] getAdvisors();
Class[] getProxiedInterfaces();
boolean isFrozen();
Reference
1. http://docs.spring.io/spring/docs/2.5.x/reference/aop.html#aop-proxying
2. http://codeomitted.com/around-advice-example-with-proxyfactory/
3. http://www.java2s.com/Code/Java/Spring/ProxyFactoryAddAdvisor.htm
4. http://www.java2s.com/Code/Java/Spring/ProxyFactoryAddAdvisor.htm
5. http://www.intertech.com/Blog/secrets-of-the-spring-aop-proxy/
TargetSource
A TargetSource is used to obtain the current "target" of an AOP invocation.Spring offers
the concept of a TargetSource, expressed in
the org.springframework.aop.TargetSource interface. This interface is responsible for
returning the "target object" implementing the join point. Target source must return
target instance each tie AOP proxy handles method invocation. a pooling TargetSource
can return a different target instance for each invocation, using a pool to manage
instances.
SingletonTargetSource will return the same instances in all cases when the getTarget()
method is called. However, TargetSource interface allows us to get Target object from
pool or factory.
Example:
PhotoSnapper obj2=(PhotoSnapper)factory.getProxy();
Advised advised=(Advised)obj2;
try{System.out.println(advised.getTargetSource().getTarget().getClass());
System.out.println("Singleton Check="+(advised.getTargetSource() instanceof
SingletonTargetSource));
}catch(Exception e){}
HotSwappableTargetSource
This enables us to swap the target object under proxy in a thread safe manner.
@Override
public void snap() {
System.out.println("I am Inside MyInterfaceImpl");
}
3. MyInterfaceImpl2.java where you define you business methods [ We are going to
swap MyInterfaceImpl object with MyInterfaceImpl2 object ]
package ch6.demo.targetsource;
@Override
public void snap() {
System.out.println("I am inside MyInterfaceImpl2");
}
}
<context:annotation-config></context:annotation-config>
<context:component-scan
base-package="ch6.demo.targetsource">
</context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-
autoproxy>
<bean id="target1" class="ch6.demo.targetsource.MyInterfaceImpl">
</bean>
<bean id="target2"
class="ch6.demo.targetsource.MyInterfaceImpl2">
</bean>
<bean id="swapper"
class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg ref ="target1"/>
</bean>
<bean id="swappable"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref ="swapper" />
</bean>
</beans>
5. Logger.java where you define advices
package ch6.demo.targetsource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class Logger {
@Pointcut("execution(* ch6.demo.targetsource.MyInterfaceImpl.snap()) ||
execution(* ch6.demo.targetsource.MyInterfaceImpl2.snap())")
@Before("cameraSnap()")
public void beforeAdvice() {
System.out.println("Before advice ...");
}
}
6. TestApp.java contains application logic to test your application.
package ch6.demo.targetsource;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.target.HotSwappableTargetSource;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import ch6.demo.aop.MessageDecorator;
import ch6.demo.aop.MyPointCut;
}
Pooling Target Sources:
PrototypeTargetSource:
</bean>
2. Put following codes in TestApp.java
MyInterface target3 = (MyInterface) context.getBean("myBean1");
target3.snap();
Reference:
1. http://itmyhome.com/spring/aop-api.html
2. https://technology.amis.nl/2005/06/19/pulling-the-rug-from-under-your-feet-while-
keeping-standing-using-the-hot-swappable-target-source-in-spring-aop/
1. Throwing an Exception
2. Returning value instead of calling proceed
Example:
1. Inside ch6.aop.targetsource package create a class named
MessageDecorator.java which implements Advice methods as shown below:
package ch6.demo.targetsource;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
@Override
public String invoke(MethodInvocation invocation) throws Throwable {
// TODO Auto-generated method stub
System.out.println("Hello000 ");
try{throw new ArithmeticException("Stopping Interceptor Chain
Early"); }catch(Exception e){System.out.println(e);}
return "asd";
//Object retVal=invocation.proceed();
//System.out.print("!");
//return retVal;
}
@Override
public String invoke(MethodInvocation invocation) throws Throwable {
// TODO Auto-generated method stub
System.out.println("Hello000 ");
try{throw new ArithmeticException("Stopping Interceptor Chain
Early"); }catch(Exception e){System.out.println(e);}
return "asd";
//Object retVal=invocation.proceed();
//System.out.print("!");
//return retVal;
}
}
It is possible to configure to expose proxy itself such that you can retrieve the
proxy and invoke advised methods on the proxy from the target object. In order
to expose proxy, you have to do following:
factory.setExposeProxy(true);
Sometimes target object needs to see the method invocation. For this, we need
to expose the current method invocation. To expose current method invocation,
you have to include following in your beans.xml file
<bean id="exposeInvocation"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="targetClass">
<value>org.springframework.aop.interceptor.ExposeInvocationInterceptor</value>
</property>
<property name="targetField"><value>INSTANCE</value></property>
</bean>
<bean id="swappable"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref ="swapper" />
<property name="exposeProxy"><value>true</value></property>
<property name="interceptorNames">
<list>
<value>exposeInvocation</value>
</list>
</property>
</bean>
AspectJ and AspectWerkz Integration
AspectJ and AspectWerkz Integration are two powerful AOP framework. We can
integrate these frameworks in Spring to build sophisticated AOP support in Spring.
AspectJ Integration
AspectJ is an extension to the Java language that elevates aspects and pointcuts to
language level constructs.
Reference:
https://dzone.com/articles/aop-made-easy-aspectj-and
AspectWerkz Integration