Monday, January 20, 2014

Spring Course: V76 - V90 Aspect Oriented Programming (AOP)

V76: A Base Project for working with Aspects
nothing here we just created a new project, in order to use aspect oriented you should add the required jar file, spring-aspects.jar

V77: A simple Aspect Example
in this tutorial we will use xml file to configure an aspect:
1- we create a camera class

2- we create a log class

3- we will define a before aspect for the snap() method

as you can see we define a pointcut and before aspect


V78: Annotation based aspect
in this tutorial we will define an aspect using annotation

1- the log class will look like this

as you see we define @aspect, usually we define a @Pointcut on a dummy method, and @Before on the method.

2- you should configure your xml and add <aspectj-autoproxy>

V79 Wildcard in Pointcut

you can add wildcard when you define your pointcut

as you can see you can use "*" instead of the method name, the return type, the package name, you can use ".." which means any argument

V80: Advice Types
we have different advice types

the most important one is @Around

V81: Proxies Interfaces and Aspects
there is an important idea here:
lets say that you have a class Camera, and we have an Aspect that intercepts Camera's methods,
what Spring does in the background is creating a Proxy class which is a subclass of Camera, and when you do
context.getBean(); it will return an instance of the Proxy class not the Camera class.
you can check that by writing
Object obj = context.getBean("camera");
System.out.println("Class of camera bean: " + obj.getClass());
System.out.println(obj instanceof Camera);

Note: sure in case we dont have any aspects Spring will return an Object of type Camera, but because we have Aspect that intercepts Camera it will return a Proxy

this is fine, however lets say that Camera implements an interface
public class Camera implements PhotoSnapper {...}

now if you run the same code
Object obj = context.getBean("camera");
System.out.println("Class of camera bean: " + obj.getClass());
System.out.println(obj instanceof Camera); //false

you will notice that Spring will return a Proxy but this time the Proxy is not Subclass of Camera, it is a subclass of the interface.

if you implement multiple interfaces
public class Camera implements PhotoSnapper, XXX {...}

The Proxy will be a sub class of both PhotoSnapper and XXX (something like public class Proxy implements PhotoSnapper, XXX{})

Note: Spring creates this proxy class to add the interception logic.

we have a problem here:

lets say Camera class looks like this

public class Camera implements PhotoSnapper {
public void snap() {
System.out.println("SNAP!");
}
}

public interface PhotoSnapper {

}

as the proxy is instance of PhotoSnapper not Camera, you cannot call the snap() method any more, because the Proxy is not an instance of Camera any more, it is an instance of PhotoSnapper which doesnt have the snap() method.

so in this case to call the snap() method you should not implement any interface, so Spring will create a proxy of type Camera.

or you can change the way Spring handle proxies, you can tell Spring to always return an instance of type Camera not an instance of the interface type by adding the following to your beans.xml

<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
proxy-target-class="true" tells spring to always return an instance of the base class.

be careful that in this case Spring will create a bean from the target class and from the Proxy(a subclass of the bean) which mean if you have a constructor for example it will be called twice

another way to handle this is to define an interface ICamera for example, put the snap() method in the ICamera and implement it in Camera, by that you dont have any problems because the Proxy that spring retuns will be an instance of ICamera, which means you can call its methods which means you can call the snap() method.

V82: Within Pointcut Designator
we were using execution to define pointcuts
@Pointcut("execution(* com.spring.aop.Camera.snap())")

there is another designator which is within, which means match within package
@Pointcut("within(com.xyz.someapp.trading..*)")

V83: “This”, “Target” and Matching Subpackages
another designators are Target and This

Target is used to target a specific class
@Pointcut("Target(com.spring.aop.Camera)")

This is used to refer to the Proxy that is created from the target class

V84: Annotation-Specific PCDs
you can target classes or methods that have specific annotations

@Pointcut("within(@Deprecated com.spring.*)")
which means targe only classes which are annotated by deprecated

you have alot of other ways to do that you can check them

V85: The Bean PCD
you can target a specific bean
@Pointcut("bean(*camera)")

which means all beans with ID ends with camera

V86: The Args PCD
you can target methods which have specific args
@Pointcut("args(int)")

all methods that takes one int arg

V87: Getting Target Method Arguments


you can use JoinPoint as a parameter in your interceptor to get information about the intercepted method

V88: Getting Arguments Using “Args”
i really didnt like this video, i dont think i am gonna use what is mentioned here

V89: Combining Pointcuts
you can combine pointcuts using && or || or !
@Before("targetCamera() && somePointcut(exposure, aperture)")

V90: Introductions: Adding Functionality Using Aspects
in this tutorial he talked about the follwoing idea:
Imagine that you have multiple classes that should implement an interface, you can write an aspect and tell the aspect that these classes should implement this interface:


as you can see we defined private IMachine machine, which is the interface that we want the classes to implement, use @DeclareParents, in value attribute we set the classes that should implement IMachine, defaultImpl is the class that implement the IMachine interface

So rather than go to all the classes and make them implement IMachine interface, you can use Aspectj


TYPES OF WEAVING
we have 3 types of weaving,
compile time: happens when we compile
loadtime: happens when the class is loaded
runtime:

No comments:

Post a Comment