350 likes | 450 Vues
Explore the evolution and challenges of Aspect-Oriented Programming (AOP) and how lightweight solutions with proxies can enhance encapsulation and separation of concerns. Learn about the concept of AOP, the importance of proxies, and the potential of dynamic behavior changes in AOP infrastructure.
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