350 likes | 440 Views
Aspect-Oriented Programming with Runtime-Generated Subclass Proxies and .NET Dynamic Methods. eva Kühn, Gerald Fessl, Fabian Schmied Institute of Computer Languages – Space-Based Computing Group Vienna University of Technology, Austria fabian@complang.tuwien.ac.at.
E N D
Aspect-Oriented Programmingwith Runtime-Generated Subclass Proxiesand .NET Dynamic Methods eva Kühn, Gerald Fessl, Fabian Schmied Institute of Computer Languages – Space-Based Computing Group Vienna University of Technology, Austria fabian@complang.tuwien.ac.at
Aspect-Oriented Programming • “New software development paradigm for better encapsulation and separation of concerns” • Goal: Allow encapsulation of cross-cutting concerns • Concerns which don’t follow the usual object-oriented or procedural decomposition of a problem • Examples: security checks, data persistence, monitoring (method call tracing) • These often don’t fit well in object-oriented designs
Aspect-Oriented Programming • Better encapsulation by augmenting existing paradigm, eg. OOP • Add new constructs for cross-cutting concerns • Base code: ordinary, object-oriented code • Deals with main (mostly functional) concerns • Aspect: encapsulates a cross-cutting concern • Influences base code • Join point: points at application runtime where aspects influence base code behavior • Introduction: static changes to base code’s type structure
Current Status of AOP • Mostly research • Concepts not sharply defined • Experimental tools, research papers, still being investigated • Very slowly adopted by industry • Mostly companies doing their own AOP research as well • Mostly Java • Reference tool: AspectJ • De-facto reference implementation • JBoss AOP • Spring AOP
AOP and .NET • Some .NET implementations exist • NAspect • AspectC# • Aspect.Net (presentation yesterday) • XL-AOF • But often immature, incomplete, unsupported (thesis works) • Little interest by Microsoft → industry • Until recently
What’s Stopping AOP? • Concept in the flow • No clear definition, still researched • Technical immaturity • Immature, incomplete, unsupported tools • Heavyweight, awkward solutions • Difficult to install, handle, use • Skeptical users • “I don’t see what it gets me” • “It magically changes my code” • “I can’t use the tools I’m used to” • Could lightweight solutions solve these problems?
Lightweight AOP • Concept in the flow • No clear definition, still researched • Technical immaturity –lightweight infrastructure needed • More mature and completed tools • Lightweight solutions • Easy to install, handle, use • Skeptical users – lightweight infrastructure helps as well • “I don’t see what it gets me” • “It relies on concepts I know” • “It’s compatible to and complements the tools I’m used to” • Concentrate on these points
Proxies - A Lightweight Solution? • NAspect, Aspect#, XL-AOF use a common infrastructure: subclass proxies • Lightweight infrastructure • Good feature set for AOP • Good potential for adoption • We provide an analysis of this infrastructure in the context of aspect-oriented programming
What’s an AOP Infrastructure? • To implement AOP, a tool must provide a mechanism for weaving • Aspect code is combined with base code • Can be done by a compiler, preprocessor, postcompiler • Can also be done at runtime dynamic weaving • Static structure is changed via introduction • Dynamic behavior is changed at join points • Aspect code needs to be inserted there • Either by manipulating code or by intercepting the join points • Infrastructure implements weaving mechanism
What’s a Proxy, Why a Proxy? • “A proxy P is an object which acts as a placeholder for a target object T” • Wherever T is expected, the proxy can be used instead
What’s a Proxy, Why a Proxy? • “A proxy P is an object which acts as a placeholder for a target object T” • Wherever T is expected, the proxy can be used instead
What’s a Proxy, Why a Proxy? • “A proxy P is an object which acts as a placeholder for a target object T” • Wherever T is expected, the proxy can be used instead • Transparently extending the target object’s behavior • Without client code noticing • This can be used for an AOP infrastructure • T is the base code • P extends the base code • Transparently intercepting object access • Invoking aspect code whenever join points are reached • P adds introduced interfaces
Proxy Kinds • .NET-provided proxies: transparent proxies • Made for Remoting • Advantage: completely transparent to client code • Disadvantage: quite restricted from AOP perspective • Custom proxies: not fully transparent • Client code must use special factories to create objects • Afterwards: transparent • Two kinds • (Proxy pattern (GoF): interface proxies) • Subclass proxies
Subclass Proxies • ClassP derives from T • Join Points: overrides methods • Introduction: implements additional interfaces
Subclass Proxies • ClassP derives from T • Join Points: overrides methods • Introduction: implements additional interfaces
Runtime-Generated SC Proxies • For dynamic weaving, proxies must be generated dynamically • Override methods part of join points • Implement interfaces for introduction • This can be done using CodeDOM or Reflection.Emit • For source code, see the paper
What About Instance Data? • Aspects often coupled to base objects • Need to access instance data to implement concerns • E.g. persistence aspect • Subclasses are not allowed to access instance data • Reflection.FieldInfo.GetValue • Possible • Very slow • Solution: Dynamically create accessor methods for instance data needed by aspects • This cannot be done using classic Reflection.Emit • But it can be done using Lightweight Code Generation
Lightweight Code Generation • LCG allows to create methods at runtime • Can be associated with any loaded type • Can also access private members of that type • Without needing to disable visibility checks • Needs ReflectionPermission to emit code • Methods are accessed via typesafe delegate • Much faster than Reflection
Concept Analysis • Subclass proxies have positive properties regarding • Invasiveness: they don’t touch existing code • Debuggability: debugging just works as is • Implementation effort: very lightweight and easy to use • Tool compatibility: all standard .NET tools can still be used • Language support: all .NET languages work • Changeability: dynamic weaving on per-instance basis • They have negative properties as well • Restricted join point model • Factory needed for object instantiation • Performance
Concept Analysis • Subclass proxies have positive properties regarding • Invasiveness: they don’t touch existing code • Debuggability: debugging just works as is • Implementation effort: very lightweight and easy to use • Tool compatibility: all standard .NET tools can still be used • Language support: all .NET languages work • Changeability: dynamic weaving on per-instance basis • They have negative properties as well • Restricted join point model • Factory needed for object instantiation • Performance ?
Performance? • Object creation • Proxies are created here • This takes a lot of time • Milliseconds instead of nanoseconds • Proxies can be cached • Subsequential instantiations are nearly as fast as ordinary new • Method invocation • In theory: very fast • Override method • In practice: tradeoff • Easier to implement if using delegates to encapsulate base method • 50ns instead of 5ns
Performance? • Realistic scenario • Many instantiations of few types • Doesn’t matter whether 5 ns or 50 ns per method call • No huge performance impact • Examples we looked at • Distributed, space-based applications • No difference observable • Bottlenecks are not object instantiation or method call times • But algorithms and resources (e.g. network time)
Summary • Proxies are a lightweight way to implement AOP • Reflection.Emit • Subclass proxies work well as an infrastructure • Join points via interception, introduction via interface • Access to private data via Lightweight Code Generation • Positive and negative properties • Positive properties: dynamic, lightweight, adoptability • Negative properties: limited join point model • Use-case dependent: performance
Properties of Proxy-Based AOP • Proxies are created at runtime • Dynamic weaving • Proxies are able to provide a join point model • Instantiation • Method calls • Property access • Finalization • Proxies can implement additional interfaces • Introduction • Proxying is transparent to client code/base code
A Note on Introduction in C# class Dog { public void Bark(){ Console.WriteLine("Bow-wow"); } } // Aspect adds Owner property at runtime Dog dog = …; dog.Bark(); Owner o = dog.Owner;
A Note on Introduction in C# class Dog { public void Bark(){ Console.WriteLine("Bow-wow"); } } // Aspect adds Owner property at runtime Dog dog = …; dog.Bark(); Owner o = dog.Owner; compile-time checked
Solution for Dynamic Weaving class Dog { public void Bark(){ Console.WriteLine("Bow-wow"); } } // Aspect adds IOwnerinterface at runtime Dog dog = …; dog.Bark(); Owner o = ((IOwner)dog).Owner;
Solution for Dynamic Weaving class Dog { public void Bark(){ Console.WriteLine("Bow-wow"); } } // Aspect adds IOwnerinterface at runtime Dog dog = …; dog.Bark(); Owner o = ((IOwner)dog).Owner; runtime checked
Unproxied Scenario • Client code uses target object directly • This reference points to the target object • Self-calls are correctly delivered • A transparent solution should expose the same behavior
Transparent Proxies • CLR automatically creates proxy object P • Client uses P transparently, P delegates to T • This reference is automatically corrected • Problem 1: self-calls are not handled by the proxy • Problem 2: introduction • Problem 3: need to inherit from ContextBoundObject
Interface Proxies • Client code uses object via interface I • Proxy implements the interface, delegates to target • Problem 1: this reference points to T instead of P • Problem 2: self-calls are not detected by the proxy • Problem 3: usage only via I (not transparent at all)
Subclass Proxies • ClassP derives from T, overrides methods, delegates to base implementation • This reference, self-calls are correctly handled • Problem: only virtual method calls can be join points
Adoptability • Non-invasive Reliability • Doesn’t touch my code • Uses ordinary OO mechanism (subclassing) • Tool compatibility • Debugging works • No need to switch tools • Framework-based • Finished tools • Less implementation effort • Easier to get right • Not as powerful as other AOP approaches