400 likes | 592 Views
AspectWerkz. Plain Java AOP. Presented by: Gal Ostfeld. January, 2005 Technion, Israel. Trivia. Founded Q4 / 2002 Founders: Jonas Boner, senior software engineer at BEA Alexandre Vasseur, software engineer at BEA Open source, by “codehaus” project Sponsored by BEA. Presale….
E N D
AspectWerkz Plain Java AOP Presented by: Gal Ostfeld January, 2005 Technion, Israel
Trivia • Founded Q4 / 2002 • Founders: • Jonas Boner, senior software engineer at BEA • Alexandre Vasseur, software engineer at BEA • Open source, by “codehaus” project • Sponsored by BEA
Presale… • AspectWerkz is a simple, high-performant, dynamic, lightweight and powerful AOP for Java • AspectWerkz offers both power and simplicity and will help you to easily integrate AOP in both new and existing projects • AspectWerkz is a Java only solution that integrates smoothly into current development processes, IDEs, tools etc. without extending Java language • AspectWerkz has been designed to have an extensible AOP aspect container where any kind of aspects can coexist, such as: AspectJ, AOP Alliance, Springetc.
Diving in – “Hello World!” package testAOP; public class HelloWorld { public static void main(String args[]) { HelloWorld world = new HelloWorld(); System.out.println(world.greet()); } public String greet() { return "Hello World!"; } }
Aspect methods need to take the JoinPoint argument otherwise the AspectWerkz weaver won't be able to identify the method when the aspect is weaved in • JoinPoint contains metadata & RTTI of this join point • In AspectWerkz 2.0 StaticJoinPoint can be used when RTTI access isn’t needed, thus optimizing performance Now we write the aspect code package testAOP; import org.codehaus.aspectwerkz.joinpoint.JoinPoint; public class MyAspect { public void beforeGreeting(JoinPoint joinPoint) { System.out.println("before greeting..."); } public void afterGreeting(JoinPoint joinPoint) { System.out.println("after greeting..."); } }
AspectWerkz call order Aspect class requirements Any Java class can be an aspect providing… • The class must be public • The method implementing the advice must be public • There must be one of these two c’tor-s defined: • An implicit/explicit default (no-arg) c’tor • A c’tor taking an AspectContext instance as its only param (enables to retrieve info about the runtime system, access deployment time param-s, access meta-data etc.) If no c’tor is found - an exception is thrown
Specifying pointcuts and advicemethods • At this point we have the test application and the actual aspect code • We still need to tell AspectWerkz where to insert the aspect methods (“pointcuts”), and which aspect method to actually insert (“advice”) • Specifying pointcuts and advice can be done using either of (or a mixture of), the following methods…
The pointcut name is only used to bind the advice Wildcards The name of the method implementing the advice before/after/around Method #1: XML definition file Loose coupling – code reuse Supports late (deployment time) binding Aspect class name holding advices <aspectwerkz> <system id="AspectWerkzExample"> <package name="testAOP"> <aspect class="MyAspect"> <pointcut name="greetMethod" expression="execution(* testAOP.HelloWorld.greet(..))"/> <advice name="beforeGreeting" type="before" bind-to="greetMethod"/> <advice name="afterGreeting" type="after" bind-to="greetMethod"/> </aspect> </package> </system> </aspectwerkz> Output: before greeting... Hello World! after greeting...
Method #2: Annotations Adding metadata to actual aspect class – self contained & self defined aspect package testAOP; import org.codehaus.aspectwerkz.joinpoint.JoinPoint; public class MyAspectWithAnnotations { /** * @Around execution(* testAOP.HelloWorld.greet(..)) */ public Object yeller(JoinPoint joinPoint) { Object greeting = joinPoint.proceed(); return "<yell>" + greeting + "</yell>"; } } Definition is strong coupled to this app It is refactoring/tool friendly In Java 1.3/1.4, annotations are defined in JavaDoc style (In Java 1.5, Java annotations are used) Call joinPoint.proceed() to invoke the next advice in the chain (or the target method if there are no more advices) which will return the result from the next advice in the chain (or the target method)
Method #2: Annotations (cont.) First you need to compile your aspect class files. Then run a special AspectWerkz tool known as the AnnotationC compiler (unless you use Java 5’s annotations) <aspectwerkz> <system id="AspectWerkzExample"> <aspect class="testAOP.MyAspectWithAnnotations"/> </system> </aspectwerkz> You still have to create a tiny XML 'stub' which tells the AspectWerkz runtime system which Java classes it should load and treat as aspects Output: <yell>Hello World!</yell> Combining XML and annotations can still make the code reusable – though less tool friendly
Weaving in and running aspects • There are two kinds of ways to actually weave the code together: • Online weaving Performs weaving as classes are loaded into the JVM • Offline weaving Done before the code is actually run • Performing the weaving is done by using the AspectWerkz tool to run java with the relevant classes, pointing it to the definition XML file/stub • Doesn't modify any of the application classes • Hot deployment and undeployment of aspects • Amends your actual application classes definition • Running the aspect is just a matter of invoking the main class • Statically compiled code can be highly tuned In both cases you need AspectWerkz jar-s on your classpath and you need to provide an XML definition file/stub
Weaving schemes AspectWerkz offers three weaving schemes: • Post compilation of the application: offline weaving at application build time • Class load time weaving: online weaving at application deployment time • Runtime weaving: online weaving in a running application
Online weaving – how is it done? • Java 5 - The AspectWerkz weaver is embedded as a Java standardized preMain agent in the JVM and thus activated transparently before any call to the main method • HotSwap (Java 1.4) - A 1st tiny JVM launches your target application in a 2nd JVM. The 1st JVM hooks AspectWerkz in the 2nd before the main class + dependencies gets loaded • Bootclasspath (Java 1.3) - Putting an enhanced class loader in the JVM bootclasspath • BEA JRockit - The AspectWerkz weaver is embedded as a ClassPreProcessor (native mechanism) component in the JRockit JVM
Hot deployment DeploymentHandle deploy ( Class aspect, String xmlDef, DeploymentScope scope, ClassLoader deployLoader ) DeploymentHandle-s can be used for undeployment - they allow you to undeploy the aspect you deployed and be sure that it will be undeployed exactly the way it was deployed This is useful only for aspects that have XML definitions - they can have annotations as well, if so then the XML definition will override the annotation definition
Hot undeployment • void undeploy(Class aspect) • void undeploy(Class aspect, ClassLoader loader) • void undeploy(DeploymentHandle deploymentHandle) All join points that were affected by a deployment event will be reverted to the state they were in before the deployment occurred. This means that we need to keep track of order and dependencies DeploymentHandle is used to revert to the state before that deployment event defined by the handle occurred
Deployment scope • It’s a special kind of pointcut which will prepare the application and advise the points that we’re interested in doing hot deployment on later • We can then retrieve a handle to this deployment scope and be sure that our aspect will be deployed at valid points in our code that suit us <deployment-scope name="toString" expression="execution(String *.toString())"/> DeploymentScope scope = SystemDefinition.getDefinitionFor(loader, systemId) .getDeploymentScope("toString");
Pointcut language(some more presale) AspectWerkz supports a fine-grained pattern language for picking out pointcuts
Pointcut language - wildcards You can utilize three types of wildcards when Constructing your patterns: • “*” - Is used as a regular wildcard. Matches for example only one package level or one method parameter • “..” - Two uses: • To match any sequence of characters that start and end with a "." (so it can be used to pick out all types in any sub-package) • In method selectors, to match as many parameters as possible • “+” - Is used to pick out all subtypes of a type (including the type itself)
Pointcut language –pointcut composition To compose pointcut expressions you can use the following logical operators: • ! - logical not • || or OR - logical or • && or AND - logical and • () - for grouping
Pointcut language – class selection !private com.*.Stam* public static com.pack.Stam private com.package.Stam2 com.company.sub.Stam3
Pointcut language – method selection int method(*,java.lang.*,Number+) int method(int i, String s, Long l) int method(int i1, int i2, Long l) int method(int i, Long l) Java.lang.* me*o*(int,..) StringBuffer method(int i) String meo(int i, String s , Object o) int method(int i, double d).
Pointcut language – field selection java.lang.* *_* StringBuffer m_ int s_inputString String _
Pointcut language – pointcut types • execution() – method or c’tor execution • call() – method or c’tor call • set() - field modification • get() – field access • handler() – (before) catch clause • within() - picks out a type set • withincode() - picks out a method or c’tor set • hasmethod() - picks out a class that has a method or c’tor matching a given pattern • hasfield() - picks out a class that has a field matching a given pattern • args() - filter method or c'tor param-s and field types and retrieving and keeping references to them. • this()/target() - narrow a pointcut expression based on caller/callee types or gain access to them in the advice • cflow() - defining a control flow
Pointcut references –code reuse • Pointcuts defined in one aspect can be referred in another aspect definition. • This can be very useful when building up pointcut libraries that need to be used throughout a project or multiple projects.
Passing parameters to aspects • There’s an option of passing parameters to aspects • This can be very convenient in order to reuse the same aspect but with a different configuration • To pass a parameter to the aspect add a param tag to the aspect definition: <aspect ... > <param name="timeout" value="10"/> </aspect> • To get the parameter (from within an aspect) use the AspectContext.getParameter(String paramName) method to retrieve the parameter value (as a String) • To set a new (or override) a parameter (from within an aspect) use the AspectContext.setParameter(String paramName, String paramValue) method
Deployment models AspectWerkz supports four different deployment models, which define the scope of the Aspect: • perJVM - one instance per JVM • perClass - one instance per class • perInstance - one instance per instance • perThread – one instance per thread
Extensible aspect container architecture - background • In recent years the Java AOP landscape has become filled with a whole bunch of frameworks, each one with its own way of defining and instantiating its aspects and with its own weaver, runtime environment and tools • This isn’t making it easier for new users of AOP and doesn’t speed up its adoption • Most existing frameworks have a lot in common
Extensible aspect container architecture - outcome • The above situation encouraged AspectWerkz designers to design an open architecture that allows you to plug in extensions that can handle the framework specific details, while the common things are shared • AspectWerkz architecture holds a weaver and a container that can weave, deploy and run any aspect no matter how it is implemented and defined • Thus there’s a basis for standardization on tools (development and runtime manageability)
Extensible aspect container architecture - example Let’s illustrate what happens when a method has been advised by a “before” advice on “execution” (callee) side: time unadvised application
Extensible aspect container architecture – conclusions • The diagram will be the same no matter how the advice has been implemented • There are parts (like "how to get the advised member arguments?" ) that are independent of the implementation details of the aspect and thus can be solved in the same way no matter what framework we would use (→part of the aspect container) • Other parts (like "how to get an aspect instance?“) that are framework specific (→part of the extension implementation)
AspectWerkz 2.0 modules Extensible aspect container architecture - illustration Each extension is seen as an aspect model and is implemented by implementing the AspectModel interface Aspects from different aspect models can coexist in one single runtime environment Aspects belonging to different aspect models
AspectWerkz custom extensions If you want to plug in your own AOP framework into the AspectWerkz Extensible Container then: • Implement the AspectModel interface public interface AspectModel { String getAspectModelType(); boolean requiresReflectiveInfo(); AroundClosureClassInfo getAroundClosureClassInfo(); void defineAspect(..); void createMandatoryMethods(..); void createInvocationOfAroundClosureSuperClass(..); void createAspectReferenceField(..); void createAspectInstantiation(..); void createAroundAdviceArgumentHandling(..); void createBeforeAdviceArgumentHandling(..); void createAfterAdviceArgumentHandling(..); } • Register your extension and the container will manage the weaving, deployment, life-cycle management etc.
AspectWerkzthe next generation AspectWerkz intends to have one single aspect container and internal representation but make the weaver pluggable, so that different strategies of doing the actual weaving could be plugged in
Benchmark • All advices did the same amount of work • The numbers in the table show how many nanosec-s per iteration, where an iteration is the invocation of the advice and the advised method • “after” advices produced identical results as “before” advices • The best performance (of advised invocation) per advice type is colored green
Benchmark results analysis • The Spring extension was as expected much faster than the Spring system since it enjoyed the optimization benefits of static compilation • AspectJ, AspectJ extension and AspectWerkz were pretty similar in the “before” (and “after”) advices • The “around” advices’ landslide of AspectJ over AspectJ extension and AspectWerkz is explained by the AspectJ compiler inlining the advice body in the target class
News flash:Last minute update… In the last few days the AspectWerkz site has released the following statement: “The AspectJ and AspectWerkz projects have agreed to work together as one team to produce a single aspect-oriented programming platform building on their complementary strengths and expertise…”
News flash:Last minute update…(cont) “The combined strengths of the two teams will enable us to deliver a more comprehensive technology suite more quickly than either team could alone. The backing of two major vendors (IBM and BEA) and a large open source community will accelerate the adoption of AOP in the enterprise…”
News flash:Last minute update…(cont) “This will begin with an extension to the AspectJ language to support an annotation-based style of development, and with tighter integration of load-time weaving for AspectJ in the J2EE environment… AspectJ 5 will also have extended deployment options for load-time weaving, supporting aop.xml deployment files in the style of AspectWerkz.”
Summary • Powerful, expressive and simple AOP framework • JLS compatible (does not extend Java) • Definition syntax in XML or annotations (or JavaDoc style annotations) • Build time/Load time/Run time weaving • Hot Deployment and Undeployment • High performance • Tailored for dynamic and static AOP in real world applications • Infrastructure extendable to be compatible with other AOP frameworks