Aspects of AspectJ
This time I will share my experience with AspectJ.
Aspects evolve for the separation of cross cutting concerns from the business logic.
The cross cutting concerns evolve Logging,Transaction Management,Security Concerns etc. i.e. anything that is not inherently related with Business Logic.
For implementing aspects we need to know about AspectJ programming syntax, which are not exact replica of java files but almost similar and follows all oops concepts.
The source files are with extension .aj and the source files are compiled to .class files(in exact bytecode format like normal java class files) by the AspectJ compiler so that any JVM can execute the compiled aspects.
Whenever we talk about aspects one term always comes to our mind that is WEAVING.
Aspects are woven into the source code at
1) Compile time (Compile Time Weaving)
2) Load Time (Load Time Weaving)
3) Run Time (This approach is proxy based and it is being used by Spring 3.0 Aspects using JDK or CGLIB bases proxies)
Now the approaches of Compile Time and Load Time approaches will come up in the Next Post, Until then Happy Reading and Productive Coding...
Here I will provide the Compile Time and Load Time approaches for AspectJ
Load Time Weaving (With Application Context(Spring))
1) Load Time Weaving for Standalone is carried out with the help of Spring Application Context and a Java (5+) Agent. (Note: The javaagent performs the runtime Byte Code Transformation with ByteCodeTransformer classes) Now for deploying in Application Servers , javaagent can be configured in the server startup script when the JVM of the server gets started (by placing thejava agent as an argument during JVM start)
OR
With the help of custom configurations (depending on the application server type).
2) A normal Java project specifying Aspects (For example SpringLTWAspectJ) is created. The Aspects are created with Annotations in java files.
3) Now a resource file is created in the Aspect project (aop.xml, should be in classpath) specifying the classes (targets) to be weaved and the aspects to be applied against those targets during Load Time Weaving (LTW).
4) Now, the AspectJ project is compiled with javac and the corresponding jar is made containing the resource aop.xml in the META-INF directory of the jar.
5) In another java project (SpringLTWAspectTarget) the target to be applied is created, along with the Spring Application Context containing the Target class bean definition and the load time weaver to be used for weaving the target classes with Aspects at Load Time.
6) This Load Time Weaver detects the aop.xml from step 4 (as jar present in the classpath) and does the weaving process accordingly with the help of javaagent (as mentioned in Step 1).
7) In this case (Standalone) we have to start the Main class with a javaagent present in Spring Intrumentation jar file specifying the jar in the VM arguments as "-javaagent:"C:/Users/hcl/Desktop/Spring Related/spring-framework-3.0.0.RELEASE/dist/org.springframework.instrument-3.0.0.RELEASE.jar"
8) Now instead of specifying the aspect with a java class with @Aspect annotation, we could also use the Aspect based programming. In this case we have to compile the aspect with ajc (AspectJ compiler) or iajc (Incremental AspectJ compiler) and put the resultant jar file and the corresponding aop.xml file in the jar file. (Please note during compilation warnings such as "no match for this type name" for pointcut defination could appear as the target is not in the classpath, so we could ignore this and proceed as Weaving would be done at Load time.
Another Approach (A slight Deviation for Good)
(Note Upto Step 4 it will be same)
Now from Step 5 there is a small change in approach for more Modularization.
5) In another java project (SpringLTWAspectTarget) the target to be applied is created and it is compiled and the jar file is made out of the compiled target classes.
6) Now, from the Actual Application from where the target is required to be invoked, the target jar and the jar from Step 4 is placed in the classpath of the application.
7) In the Actual Application, in the Spring Application Context file (applicationContext.xml as already present in the classpath) containing the load time weaver to be used for weaving the target classes with Aspects at Load Time is kept.
8) This Load Time Weaver detects the aop.xml from step 4 (as jar present in the classpath) and does the weaving process accordingly in the target classes.
9) Now the Virtual machine is started up with the agent of Step 7
Compile Time Weaving (With AspectJ based Programming)
1) Compile Time Weaving (CTW) is straightforward than Load Time Weaving (LTW)
2) Here, at first the Target jar is build.
3) Next an AspectJ Project is created (AspectJProject) and aspects (.aj files) are created accordingly. Aspects are compiled (with ajc or iajc Ant task) with the target jar as formed in Step2 in the classpath so that the pointcuts defined in the aspect files could be resolved.
4) Now a jar is made out of the .class files i.e. compiled aspect files.
5) Now the aspects formed in Step 3 is required to be weaved into the Target jar formed in step 2, with the inpath element of iajc Ant task containing the Target jar and aspectpath element of the iajc Ant task containing the aspect jar, so that the resulting jar as present in the outjar attribute of iajc contain the resulting weaved classes in jar format.
6) Now any application wishes to use this Compile Time Weaving should place the jar of Step 5 and jar of Step 4 in the classpath.
7) The essential third party lib jars for entire build process viz. 1) aspectjweaver-1.5.4.jar 2) aspectjtools-1.6.2.jar and 3) aspectjrt-1.5.4.jar (Note: Make all the versions compatible if possible)
8) After Compile Time Weaving (CTW) the weaved library of step 5 and the jar containing only the aspects should be in the classpath.
I will try to share my Experience of Coding with AspectJ with Design Pattern implementation. As during my Coding I came across various situations during Design Pattern implementation which I haven't encountered while doing simple AspectJ implementation.
Though at first I will obviously provide some basic Introductory examples of AspectJ programs
Now This is a basic working example of AspectJ
public class Myclass { static String prop1; static String prop2; public void getData() { try{ //System.out.println("*** The properties are: Prop1:"+prop1+"\n Prop2:"+prop2); System.out.println(" *** Myclass.getData() is invoked Here hehe *** "); System.out.println(new MyClass1().getData("Subha","Mic",1,new ModelImpl())); } catch(Exception e) { } } } package com.aspectj.target; public class MyClass1 { public String getData(String name1,String name2,Integer i,Model modelImpl) throws MyException { System.out.println(" *** Myclass1.getData() is invoked okay ### *** "); //throw new MyException(" Only Exception is thrown "); return " *** Success from MyClass1.getData() *** "; } public void getData2(String name,int i) { System.out.println(name+" has number"+i); } } public interface Model { } public class ModelImpl implements Model { public String toString() { return "*** Model Implementation class ***"; } }Create a jar out of the above mentioned classes and interfaces.
Now we will create an aspect which will intercept execution of all the methods within class MyClass1 having targets MyClass1 and having the last parameter in the method of type Model.
So the Aspect is:
public aspect MyAspect { pointcut incept() : execution(* com.aspectj.target.MyClass1.*(..)); pointcut cFlowIncept() : incept() && target(MyClass1) && args(..,Model); before() : cFlowIncept() { System.out.println("####"); System.out.println(" Entering into "+thisJoinPoint.getSourceLocation()+ " Kind:"+thisJoinPoint.getKind()+ " Static Part"+thisJoinPoint.getStaticPart()+ " Target:"+thisJoinPoint.getTarget()+ " This:"+thisJoinPoint.getThis()); Object[] object1 = thisJoinPoint.getArgs(); //Now Iterate through object1 array to fetch all method parameters System.out.println("####"); try{ //File file = new File("C:/Users/hcl/Desktop/CompileTimeAsp.txt"); //file.createNewFile(); } catch(Exception e) { e.printStackTrace(); } } after() : cFlowIncept() { System.out.println(" Exiting from "+thisJoinPoint.getSourceLocation()); } }Lets go into the description of the above Aspect
The pointcut incept and cFlowIncept, intercept the methods calls of the class MyClass1 with the criterion desccribed above.There are two advices associated with the pointcut. One is before advice an one is after advice. The before advice executes before the execution of the method and the after advice after the execution on the methods as mentioned with the specified criterion.
The information which gets printed in the before advice is really interesting and can be used in a variety of ways, which we will take up later on. The after advice prints only the method exit.
Now we will build a jar file containing the above mentioned advice with the help of the following ant task
<target name="init"> <taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"> <classpath> <pathelement location="${lib}/aspectjtools-1.6.2.jar"> </pathelement></classpath> </taskdef> </target> <target depends="init" name="buildAspect"> <mkdir dir="${output}"/> <ajc classpathref="MYCLASSPATH" debug="true" destdir="${output}" source="1.6" target="1.6" verbose="true"> <src location="${src}"></src> </ajc> <jar destfile="${aspectJar}/AspectLib.jar" basedir="output" includes="**/My*Aspect*.class" > <!--metainf dir="${resources}" includes="**/*.xml" ></metainf--> </jar> </target>Now we will weave the aspects as formed in the above jar in the source jar formed above with the help of the following ant task. while running the ant tasks, please keep all the relevant jars classpath as required.
<target depends="init" name="weaveAspects"> <delete dir="${finalJar}"></delete> <mkdir dir="${finalJar}"> <iajc target="1.6" source="1.6" fork="false" incremental="false" outjar="${finalJar}/AspectTarget.jar" showweaveinfo="true" debug="true" verbose="true" debugLevel="lines,vars,source" time="true" classpathref="MYCLASSPATH" > <!--sourceroots> <pathelement location="src"/> </sourceroots--> <inpath> <fileset dir="${targetJar}"> <include name="**/AspectTarget.jar" /> </fileset> </inpath> <aspectpath> <fileset dir="${aspectJar}"> <include name="**/AspectLib.jar" /> </fileset> </aspectpath> </iajc> </target>Let the source jar to be weaved is "AspectTarget.jar" and the jar containing aspects to be "AspectLib.jar", after weaving process the final jar formed is also named as "AspectTarget.jar" to avoid any confusion.
For any verification One could decompile the classes in the final jar "AspectTarget.jar" and could see the weaved code at the designated place.
Now for Testing purposes, One could place above two jars formed , i.e. "AspectTarget.jar" and the "AspectLib.jar" in a target project and could run the following code to see the magic
Myclass myclass = new Myclass(); MyClass1 myClass1 = new MyClass1(); myclass.getData();This is in short about AspectJ working example.
In my next blog I will write about the Design pattern implementation using AspectJ Till then happy reading and productive coding.
In case of any issues regarding above discussion
Abioce0ligji Angela Wilson https://wakelet.com/wake/x6ocgys-K_Glb-kHFSt7d
ReplyDeletedowsdelizi