Cours IUT - CSID 2012 An Introduction to AOP: Aspect Oriented Programming
[email protected] This document: http://arnaud.nauwynck.free.fr/CoursIUT/CoursIUT-IntroAOP.pdf
Outline ●
What is AOP ? Samples usages
●
Java.lang.Proxy, InvocationHandler
●
AspectJ
●
Bytecode Generator/Loader/Weaver
●
Java VM Agent
What is AOP (Java) ? … Google It
●
Not to confound with french “Appélation d'Origine Protégée”, or “Amplificateur Opérationnel”, ...
Wikipedia
AOP Keywords ●
AOP = Aspect Oriented Programming
●
To be compared with OO : Object Oriented
●
●
Separation of Cross-Cutting Concerns, Orthogonal Aspects in code Other Keywords: Meta-Programming, Programming Paradigm, Technical vs Functional Code, Annotation Based Programming
Cross-Cutting Concerns ? ●
Logging
●
Auditing
●
Security Check
●
Monitoring : Performance Time, Call Counters
●
Transaction Management (ACID)
●
...
Sample Aspect: Logging ●
Log : before / before+after / before+after+exceptions?
Sample Aspect: Logging “Around” with try-catch
Around Aspect: Try-catch => log
Functional Code
Sample Before Aspect for Security
Sample Aspect For Performance Time Monitoring
A Very Important “Aspect” : Transactional ●
ACID Principles: All or Nothing …
Combining 4 Simple Orthogonal Aspects...
4 x 1 Simple Aspects + N x functional Codes = ?? ●
●
●
Code is linear but no more simple / readable Copy & Paste the wrapper aspects everywhere in your code ?? not maintainable... => NEED a change of Programming Paradigm
AOP Goal = Split Concerns ●
Use 1 File/Method/Other-Langage per Aspect … (*.java Proxy, *.aj, *.xml, annotation...) = “Advice”, Proxy InvocationHandler
●
Use detection pattern to apply to N x code (*.java Proxy, *.aj, *.xml, annotation...) = “Joint Point”, “PointCut”, Proxy
●
Result Code = Combining Advice + User-Code
Solution : AOP … Spring +AspectJ
Sample Solution Code : Spring + AspectJ *.aj or @Aspect externallydefined
@Annotation based
Spring Xml Configuration
Sample Externally Defined AOP with AspectJ 1.6 (@Aspect)
Code + Pointcut/Advice => Weaved Code Compiler or Runtime Inputs
User Code1
User Code2
User Code...
Proxy Wrapper Weaved Code2
Proxy Wrapper Weaved Code2
Logging Aspect Security Aspect
Result
Intermediates ...
Transact Aspect Monitoring Aspect
Proxy Wrapper Weaved Code1
PointCut Detection Pattern ●
Define Where / Where-NOT to apply Advice User Code1 @Log, @Mon
User Code2 @Secure,@XA
User Code... @Log @XA, @Mon
Logging Aspect Security Aspect NO match Transact Aspect match Monitoring Aspect
Use Proxy and/or Weaver Compile/Runtime/Agent
Proxy Wrapper Weaved Code1
Proxy Wrapper Code2
Weaved Code 3
Weaving/Wrapping Strategies ●
LOT Of Possibilities !!!
●
User define *.java: new Proxy(..)
●
*.xml => new Proxy() in Injection context (Spring)
●
*.java => *.java
●
*.java => *.class (byte-code generator)
●
*.class => *.class (byte-code weaver)
●
*.class => ClassLoader byte[] dynamic weaver
●
byte[] => JVM agent byte[]
(javac compiler agent)
dynamic weaver
Simplest Approach : User Code on Objects... Not on Methods ●
●
“Static Method” can not be overloaded (cf Groovy) Use Object-Oriented pointer + override instead of static methods instead of
“public static void foo() {...}”
prefer: “interface IFoo { void foo(); }” + “class...implements IFoo” ●
With Typed-safe interfaces => Design Pattern names: Proxy, Adapter, Delegate, Bridge, Command, ...
Sample User Proxy / Delegate
Using java.lang.reflect.* Proxy, InvocationHandler ●
Goal: define a “generic” Proxy pattern ●
●
●
For any interface … not only for Foo/Bar classes
java.lang.reflect.Proxy for wrapping underlying object class with static methods only, no public constructor! Proxy.newProxyInstance() java.lang.reflect.InvocationHandler for handling calls to proxy methods
Sample java.lang.reflect.Proxy
Proxy
Underlying Inkoke
Debugging Stack Trace with Proxy + Method.Invoke()
● ●
traversing 6-levels at debugging-time … BUT efficient (bytecode is generated + HOTSPOT optimized)
Proxy Class : “$Proxy123..” ??
Analyzing $Proxy123 Class
$Proxy123 Class Pseudo code ●
generated bytecode ~=
transform () => proxy.h.execute(..)
Reflection Duality ... User code => Proxy Proxy => generic InvocationHandler InvocationHandler => reflect Method.invoke() Method.invoke() => user code
Method.invoke() pseudo code ●
Method are instances of java.lang.reflect.Method -> delegating to sun.reflect.MethodAccessor
●
0-1 singleton MethodAccessor per compile-time method
●
Pseudo equivalent code:
MethodAccessor Pseudo code GeneratedMethodAccessor123
Method.invoke() Optimizations ●
●
●
On first call => use delegate + NativeMethodAccessor ...after few calls => replace delegate with generated bytecode !! class “GeneratedMethodAccessor” … after many calls => bytecode is optimized natively by HOTSPOT !! Method
DelegatingMethodAccessor
MethodAccessor
NativeMethodAccessor
GeneratedMethodAccessor123
MethodAccessor Internals …
Optimized Call Stack Method.invoke() Generated / Native
Usages of java.lang.reflect.Proxy ● ●
●
Frameworks like Spring use it intensively User Interfaces not known at compilation-time but code is generic !! => at Runtime ● ●
●
Read Xml file Interpret @Annotation (@Transactional, @PreAuthenticate, ...) wrap Spring beans by Spring Dynamic Proxies
AspectJ ●
AspectJ : (eclipse.org) Open-Source project ●
A Runtime jar
●
A Compile-time weaver
●
Maven / Eclipse / … plugins
AspectJ-Maven-Plugin
AspectJ Sample in Spring-Roo ITD : Inter-Type-Definition
Class name to inject (compile-time) field / methods
Last But Not Least JVM Agent … ●
Startup & Triggers can be defined at JVM layer!
●
Keywords : ●
JVM Agent
-javaagent:myag.jar or -Xrunagent:myag.jar ● ● ● ● ●
Instrumentation ClassFileTransformer Classloading Bytecode Weaver JavaAssist / BCEL Monitoring Agent
Sample Example: onClassLoader.load => add ( => parse bytecode + inject bytecodes + write bytecode replacement )
premain(Instrumentation) … ClassFileTransformer
Bytecode => JavaAssist/BCEL =>
Conclusion Java AOP is Beautiful !! Questions ?
[email protected] This document: http://arnaud.nauwynck.free.fr/CoursIUT/CoursIUT-IntroAOP.pdf