NAME
    Aspect - Aspect-Oriented Programming (AOP) for Perl

SYNOPSIS
      use Aspect;
      
  
  
  # Run some code "Advice" before a particular function
      before {
          print "About to call create\n";
      } call 'Person::create';
      
  
  
  # Run Advice after several methods and hijack their return values
      after {
          print "Called getter/setter " . $_->sub_name . "\n";
          $_->return_value(undef);
      } call qr/^Person::[gs]et_/;
      
  
  
  # Run Advice conditionally based on multiple factors
      before {
          print "Calling a get method in void context within Tester::run_tests";
      } wantvoid
      & ( call qr/^Person::get_/ & ! call 'Person::get_not_trapped' )
      & cflow 'Tester::run_tests';
      
  
  
  # Context-aware runtime hijacking of a method if certain condition is true
      around {
          if ( $_->self->customer_name eq 'Adam Kennedy' ) {
              # Ensure I always have cash
              $_->return_value('One meeeelion dollars');
          } else {
              # Take a dollar off everyone else
              $_->proceed;
              $_->return_value( $_->return_value - 1 );
          }
      } call 'Bank::Account::balance';
      
  
  
  # Catch and handle unexpected exceptions in a function into a formal object
      after {
          $_->exception(
              Exception::Unexpected->new($_->exception)
          );
      } throwing()
      & ! throwing('Exception::Expected')
      & ! throwing('Exception::Unexpected');
      
  
  
  # Run Advice only on the outmost of a recursive series of calls
      around {
        print "Starting recursive child search\n";
        $_->proceed;
        print "Finished recursive child search\n";
      } call 'Person::find_child' & highest;
      
  
  
  # Run Advice only during the current lexical scope
      SCOPE: {
          my $hook = before {
              print "About to call create\n";
          } call 'Person::create';
      
      # Advice will run for this call
          Person->create('Bob');
      }
      
  # Advice won't run for this call
      Person->create('Tom');
      
  
  
  # Use a pre-packaged collection "Aspect" of Advice rules to change a class
      aspect Singleton => 'Foo::new';
      
  
  
  # Define debugger breakpoints with high precision and conditionality
      aspect Breakpoint => call qr/^Foo::.+::Bar::when_/ & wantscalar & highest;

DESCRIPTION
  What is Aspect-Oriented Programming?
    Aspect-Oriented Programming (AOP) allows you to modularise concerns that
    would otherwise cut across many parts of a program and be problematic to
    implement and maintain.

    One common example is logging, where many small fragments code are
    typically spread throughout your entire codebase.

    Another example is the implementation of design patterns, which combine
    or manipulate various kinds of classes in particular ways produce a
    known type of higher order behavior.

    Because Aspect-Oritented Programming moves this scattered code into a
    single place, another major benefit is conditional compilation.

    Features implemented via Aspects can be compiled in only in certain
    situations, and because of this Aspects are useful when debugging or
    testing large complex programs.

    Aspects can implement features necesary for correctness of programs such
    as reactivity or synchronisation, and it can be used to add checking
    assertions to your or other people's modules.

    If necesary (although not recommended) you can also do "Monkey
    Patching", hijacking the functionality of some other module to act
    different when used in your program than when other everywhere else.

    Aspects can be used to implement space or time optimisations. One
    popular use case is to add caching to a module or function that does not
    natively implement caching.

    See <http://www.aosd.net> for more info.

  About This Implementation
    The Perl Aspect module tries to closely follow the terminology of the
    Java AspectJ project wherever possible (<http://eclipse.org/aspectj>).

    However due to the dynamic nature of the Perl language, several
    "AspectJ" features are useless for us: exception softening, mixin
    support, out-of-class method declarations, annotations, and others.

    The Perl Aspect module is focused on subroutine matching and wrapping.

    It allows you to select collections of subroutines and conditions using
    a flexible pointcut language, and modify their behavior in any way you
    want.

    In this regard it provides a similar set of functionality to
    Hook::LexWrap, but with much more precision and with much more control
    and maintainability as the complexity of what you are doing increases.

    In addition, where the Java implementation of Aspect-Oriented
    Programming is only able to integrate at compile time, the nature of
    Perl means that the Aspect module can weave in aspect code at run-time,
    and pointcuts can take advantage of run-time information and
    Perl-specific features like closures.

    This allows the Perl implementation of Aspect-Oriented Programming to be
    stateful and adaptive in a way that Java nroamlly cannot be.

  Terminology
    One of the more opaque aspects (no pun intended) of Aspect-Oriented
    programming is that it has an entire unique set of terms that can be
    confusing for people learning to use the Aspect module.

    In this section, we will attempt to define all the major terms in a way
    that will hopefully make sense to Perl programmers.

   What is an Aspect?
    An *Aspect* is a modular unit of cross-cutting implementation,
    consisting of "Advice" on "Pointcuts" (we'll define those two shortly,
    don't worry if they don't make sense for now).

    In Perl, this would typically mean a package or module containing
    declarations of where to inject code, the code to run at these points,
    and any variables or support functions needed by the injected
    functionality.

    The most critical point here is that the Aspect represents a collection
    of many different injection points which collectively implement a single
    function or feature and which should be enabled on an all or nothing
    basis.

    For example, you might implement the Aspect My::SecurityMonitor as a
    module which will inject hooks into a dozen different strategic places
    in your program to watch for valid-but-suspicious values and report
    these values to an external network server.

    Aspects can often written to be highly reusable, and be released via the
    CPAN. When these generic aspects are written in the special namespace
    Aspect::Library they can be called using the following special
    shorthand.

      use Aspect;
      
  # Load and enable the Aspect::Library::NYTProf aspect to constrain profiling
      # to only the object constructors for each class in your program.
      aspect NYTProf => call qr/^MyProgram\b.*::new$/;

   What is a Pointcut?
    A *Join Point* is a well-defined location at a point in the execution of
    a program at which Perl can inject functionality, in effect joining two
    different bits of code together.

    In the Perl Aspect implementation, this consists only of the execution
    of named subroutines on the symbol table such as
    "Foo::Bar::function_name".

    In other languages, additional join points can exist such as the
    instantiation or destruction of an object or the static initialisation
    of a class.

    A *Pointcut* is a well-defined set of join points, and any conditions
    that must be true when at these join points.

    Example include "All public methods in class "Foo::Bar"" or "Any
    non-recursive call to the function "Some::recursive_search"".

    We will discuss each of the available pointcut types later in this
    document.

    In addition to the default pointcut types it is possible to write your
    own specialised pointcut types, although this is challenging due to the
    complex API they follow to allow aggressive multi-pass optimisation.

    See Aspect::Pointcut for more information.

   What is Advice?
    *Advice* is code designed to run automatically at all of the join points
    in a particular pointcut. Advice comes in several types, instructing
    that the code be run "before", "after" or "around" (in place of) the
    different join points in the pointcut.

    Advice code is introduced lexically to the target join points. That is,
    the new functionality is injected in place to the existing program
    rather the class being extended into some new version.

    For example, function "Foo::expensive_calculation" may not support
    caching because it is unsafe to do so in the general case. But you know
    that in the case of your program, the reasons it is unsafe in the
    general case don't apply.

    So for your program you might use the Aspect::Library::Memoise aspect to
    "Weave" Advice code into the "Foo" class which adds caching to the
    function by integrating it with Memoise.

    Each of the different advice types needs to be used slightly
    differently, and are best employed for different types of jobs. We will
    discuss the use of each of the different advice types later in this
    document.

    But in general, the more specific advice type you use, the more
    optimisation can be applied to your advice declaration, and the less
    impact the advice will have on the speed of your program.

    In addition to the default pointcut types, it is (theoretically)
    possible to write your own specialised Advice types, although this would
    be extremely difficult and probably involve some form of XS programming.

    For the brave, see Aspect::Advice and the source for the different
    advice classes for more information.

   What is Weaving?
    *Weaving* is the installation of advice code to the subs that match a
    pointcut, or might potentially match depending on certain run-time
    conditions.

    In the Perl Aspect module, weaving happens on the declaration of each
    advice block. Unweaving happens when a lexically-created advice variable
    goes out of scope.

    Unfortunately, due to the nature of the mechanism Aspect uses to hook
    into function calls, unweaving can never be guarenteed to be round-trip
    clean.

    While the pointcut matching logic and advice code will never be run for
    unwoven advice, it may be necesary to leave the underlying hooking
    artifact in place on the join point indefinitely (imposing a small
    performance penalty and preventing clean up of the relevant advice
    closure from memory).

    Programs that repeatedly weave and unweave during execution will thus
    gradually slow down and leak memory, and so is discouraged despite being
    permitted.

    If advice needs to be repeatedly enabled and disabled you should instead
    consider using the "true" pointcut and a variable in the aspect package
    or a closure to introduce a remote "on/off" switch for the aspect.

    into the advice code.

      package My::Aspect;
      
  my $switch = 1;
      
  before {
          print "Calling Foo::bar\n";
      } call 'Foo::bar' & true { $switch };
      
  sub enable {
          $switch = 1;
      }
      
  sub disable {
          $switch = 0;
      }
      
  1;

    Under the covers weaving is done using a mechanism that is very similar
    to the venerable Hook::LexWrap, although in some areas Aspect will try
    to make use of faster mechanisms if it knows these are safe.

  Feature Summary
    *   Create permanent pointcuts, advice, and aspects at compile time or
        run-time.

    *   Flexible pointcut language: select subs to match using string
        equality, regexp, or "CODE" ref. Match currently running sub, a sub
        in the call flow, calls in particular void, scalar, or array
        contexts, or only the highest call in a set of recursive calls.

    *   Build pointcuts composed of a logical expression of other pointcuts,
        using conjunction, disjunction, and negation.

    *   In advice code, you can modify parameter list for matched sub,
        modify return value, throw or supress exceptions, decide whether or
        not to proceed to matched sub, access a "CODE" ref for matched sub,
        and access the context of any call flow pointcuts that were matched,
        if they exist.

    *   Add/remove advice and entire aspects lexically during run-time. The
        scope of advice and aspect objects, is the scope of their effect
        (This does, however, come with some caveats).

    *   A basic library of reusable aspects. A base class makes it easy to
        create your own reusable aspects. The Aspect::Library::Memoize
        aspect is an example of how to interface with AOP-like modules from
        CPAN.

  Using Aspect.pm
    The Aspect package allows you to create pointcuts, advice, and aspects
    in a simple declarative fashion. This declarative form is a simple
    facade on top of the Perl AOP framework, which you can also use directly
    if you need the increased level of control or you feel the declarative
    form is not clear enough.

    For example, the following two examples are equivalent.

      use Aspect;
      
  # Declarative advice creation
      before {
          print "Calling " . $_->sub_name . "\n";
      } call 'Function::one'
      | call 'Function::two';
      
  # Longhand advice creation
      Aspect::Advice::Before->new(
          Aspect::Pointcut::Or->new(
              Aspect::Pointcut::Call->new('Function::one'),
              Aspect::Pointcut::Call->new('Function::two'),
          ),
          sub {
              print "Calling " . $_->sub_name . "\n";
          },
      );

    You will be mostly working with this package (Aspect) and the
    Aspect::Point package, which provides the methods for getting
    information about the call to the join point within advice code.

    When you "use Aspect;" you will import a family of around fifteen
    functions. These are all factories that allow you to create pointcuts,
    advice, and aspects.

FUNCTIONS
    The following functions are exported by default (and are documented as
    such) but are also available directly in Aspect:: namespace as well if
    needed.

    They are documented in order from the simplest and and most common
    pointcut declarator to the highest level declarator for enabling
    complete aspect classes.

  call
      my $single   = call 'Person::get_address';
      my $multiple = call qr/^Person::get_/;
      my $complex  = call sub { lc($_[0]) eq 'person::get_address' };
      my $object   = Aspect::Pointcut::Call->new('Person::get_address');

    The most common pointcut is "call". All three of the examples will match
    the calling of "Person::get_address()" as defined in the symbol table at
    the time an advice is declared.

    The "call" declarator takes a single parameter which is the pointcut
    spec, and can be provided in three different forms.

    string

    Select only the specific full resolved subroutine whose name is equal to
    the specification string.

    For example "call 'Person::get'" will only match the plain "get" method
    and will not match the longer "get_address" method.

    regexp

    Select all subroutines whose name matches the regular expression.

    The following will match all the subs defined on the "Person" class, but
    not on the "Person::Address" or any other child classes.

      $p = call qr/^Person::\w+$/;

    CODE

    Select all subroutines where the supplied code returns true when passed
    a full resolved subroutine name as the only parameter.

    The following will match all calls to subroutines whose names are a key
    in the hash %subs_to_match:

      $p = call sub {
          exists $subs_to_match{$_[0]};
      }

    For more information on the "call" pointcut see Aspect::Pointcut::Call.

  cflow
      before {
         print "Called My::foo somewhere within My::bar\n";
      } call 'My::foo'
      & cflow 'My::bar';

    The "cflow" declarator is used to specify that the join point must be
    somewhere within the control flow of the "My::bar" function. That is, at
    the time "My::foo" is being called somewhere up the call stack is
    "My::bar".

    The parameters to "cflow" are identical to the parameters to "call".

    Due to an idiosyncracy in the way "cflow" is implemented, they do not
    always parse properly well when joined with an operator. In general, you
    should use any "cflow" operator last in your pointcut specification, or
    use explicit braces for it.

      # This works fine
      my $x = call 'My::foo' & cflow 'My::bar';
      
  # This will error
      my $y = cflow 'My::bar' & call 'My::foo';
      
  # Use explicit braces if you can't have the flow last
      my $z = cflow('My::bar') & call 'My::foo';

    For more information on the "cflow" pointcut, see
    Aspect::Pointcut::Cflow.

  wantlist
      my $pointcut = call 'Foo::bar' & wantlist;

    The "wantlist" pointcut traps a condition based on Perl "wantarray"
    context, when a function is called in list context. When used with
    "call", this pointcut can be used to trap list-context calls to one or
    more functions, while letting void or scalar context calls continue as
    normal.

    For more information on the "wantlist" pointcut see
    Aspect::Pointcut::Wantarray.

  wantscalar
      my $pointcut = call 'Foo::bar' & wantscalar;

    The "wantscalar" pointcut traps a condition based on Perl "wantarray"
    context, when a function is called in scalar context. When used with
    "call", this pointcut can be used to trap scalar-context calls to one or
    more functions, while letting void or list context calls continue as
    normal.

    For more information on the "wantscalar" pointcut see
    Aspect::Pointcut::Wantarray.

  wantvoid
      my $bug = call 'Foo::get_value' & wantvoid;

    The "wantvoid" pointcut traps a condition based on Perl "wantarray"
    context, when a function is called in void context. When used with
    "call", this pointcut can be used to trap void-context calls to one or
    more functions, while letting scalar or list context calls continue as
    normal.

    This is particularly useful for methods which make no sense to call in
    void context, such as getters or other methods calculating and returning
    a useful result.

    For more information on the "wantvoid" pointcut see
    Aspect::Pointcut::Wantarray.

  highest
      my $entry = call 'Foo::recurse' & highest;

    The "highest" pointcut is used to trap the first time a particular
    function is encountered, while ignoring any subsequent recursive calls
    into the same pointcut.

    It is unusual in that unlike all other types of pointcuts it is
    stateful, and so some detailed explaination is needed to understand how
    it will behave.

    Pointcut declarators follow normal Perl precedence and shortcutting in
    the same way that a typical set of "foo() and bar()" might do for
    regular code.

    When the "highest" is evaluated for the first time it returns true and a
    counter is to track the depth of the call stack. This counter is bound
    to the join point itself, and will decrement back again once we exit the
    advice code.

    If we encounter another function that is potentially contained in the
    same pointcut, then "highest" will always return false.

    In this manner, you can trigger functionality to run only at the
    outermost call into a recursive series of functions, or you can negate
    the pointcut with "! highest" and look for recursive calls into a
    function when there shouldn't be any recursion.

    In the current implementation, the semantics and behaviour of pointcuts
    containing multiple highest declarators is not defined (and the current
    implementation is also not amenable to supporting it).

    For these reasons, the usage of multiple highest declarators such as in
    the following example is not support, and so the following will throw an
    exception.

      before {
          print "This advice will not compile\n";
      } wantscalar & (
          (call 'My::foo' & highest)
          |
          (call 'My::bar' & highest)
      );

    This limitation may change in future releases. Feedback welcome.

    For more information on the "highest" pointcut see
    Aspect::Pointcut::Highest.

  throwing
      my $string = throwing qr/does not exist/;
      my $object = throwing 'Exception::Class';

    The "throwing" pointcut is used with the "after" (and "after_throwing")
    to restrict the pointcut so advice code is only fired for a specific die
    message or a particular exception class (or subclass).

    The "throwing" declarator takes a single parameter which is the pointcut
    spec, and can be provided in two different forms.

    regexp

    If a regular expression is passed to "throwing" it will be matched
    against the exception if and only if the exception is a plain string.

    Thus, the regexp form can be used to trap unstructured errors emitted by
    "die" or "croak" while NOT trapping any formal exception objects of any
    kind.

    string

    If a string is passed to "throwing" it will be treated as a class name
    and will be matched against the exception via an "isa" method call if
    and only if the exception is an object.

    Thus, the string form can be used to trap and handle specific types of
    exceptions while allowing other types of exceptions or raw string errors
    to pass through.

    For more information on the "throwing" pointcut see
    Aspect::Pointcut::Throwing.

  returning
      after {
          print "No exception\n";
      } call 'Foo::bar' & returning;

    The "returning" pointcut is used with "after" advice types to indicate
    the join point should only occur when a function is returning without
    throwing an exception.

  true
      # Intercept an adjustable random percentage of calls to a function
      our $RATE = 0.01;
      
  before {
          print "The few, the brave, the 1%\n";
      } call 'My::foo'
      & true {
          rand() < $RATE
      };

    Because of the lengths that Aspect goes to internally to optimise the
    selection and interception of calls, writing your own custom pointcuts
    can be very difficult.

    When a custom or unusual pattern of interception is needed, often all
    that is desired is to extend a relatively normal pointcut with an extra
    caveat.

    To allow for this scenario, Aspect provides the "true" pointcut.

    This pointcut allows you to specify any arbitrary code to match on. This
    code will be executed at run-time if the join point matches all previous
    conditions.

    The join point matches if the function or closure returns true, and does
    not match if the code returns false or nothing at all.

  before
      before {
          # Don't call the function, return instead
          $_->return_value(1);
      } call 'My::foo';

    The before advice declaration is used to defined advice code that will
    be run instead of the code originally at the join points, but continuing
    on to the real function if no action is taken to say otherwise.

    When called in void context, as shown above, "before" will install the
    advice permanently into your program.

    When called in scalar context, as shown below, "before" will return a
    guard object and enable the advice for as long as that guard object
    continues to remain in scope or otherwise avoid being destroyed.

      SCOPE: {
          my $guard = before {
              print "Hello World!\n";
          } call 'My::foo';
      
      # This will print
          My::foo(); 
      }
      
  # This will NOT print
      My::foo();

    Because the end result of the code at the join points is irrelevant to
    this type of advice and the Aspect system does not need to hang around
    and maintain control during the join point, the underlying
    implementation is done in a way that is by far the fastest and with the
    least impact (essentially none) on the execution of your program.

    You are strongly encouraged to use "before" advice wherever possible for
    the current implementation, resorting to the other advice types when you
    truly need to be there are the end of the join point execution (or on
    both sides of it).

    For more information, see Aspect::Advice::Before.

  after
      # Confuse a program by bizarely swapping return values and exceptions
      after {
          if ( $_->exception ) {
              $_->return_value($_->exception);
          } else {
              $_->exception($_->return_value);
          }
      } call 'My::foo' & wantscalar;

    The "after" declarator is used to create advice in which the advice code
    will be run after the join point has run, regardless of whether the
    function return correctly or throws an exception.

    This advice should be used when you need to deal flexibly with return
    values, but might also want to handle exceptions. Use of this advice is
    relatively rare, as most of the time you want something more flexible
    like "around", or something more specific like "after_returning" or
    "after_throwing".

    For more information, see Aspect::Advice::After.

  around
      # Trace execution time for a function
      around {
          my @start   = Time::HiRes::gettimeofday();
          $_->proceed;
          my @stop    = Time::HiRes::gettimeofday();
      
      my $elapsed = Time::HiRes::tv_interval( \@start, \@stop );
          print "My::foo executed in $elapsed seconds\n";
      } call 'My::foo';

    The "around" declarator is used to create the most general form of
    advice, and can be used to implement the most high level functionality.

    It allows you to make changes to the calling parameters, to change the
    result of the function, to subvert or prevent the calling altogether,
    and to do so while storing extra lexical state of your own across the
    join point.

    For example, the code shown above tracks the time at which a single
    function is called and returned, and then uses the two pieces of
    information to track the execution time of the call.

    Similar functionality to the above is used to implement the CPAN modules
    Aspect::Library::Timer and the more complex Aspect::Library::ZoneTimer.

    Within the "around" advice code, the "$_->proceed" method is used to
    call the original function with whatever the current parameter context
    is, storing the result (whether return values or an exception) in the
    context as well.

    Alternatively, you can use the "original" method to get access to a
    reference to the original function and call it directly without using
    context parameters and without storing the function results.

      around {
          $_->original->('alternative param');
          $_->return_value('fake result');
      } call 'My::foo';

    The above example calls the original function directly with an
    alternative parameter in void context (regardless of the original
    "wantarray" context) ignoring any return values. It then sets an
    entirely made up return value of it's own.

    Although it is the most powerful advice type, "around" is also the
    slowest advice type with the highest memory cost per join point. Where
    possible, you should try to use a more specific advice type.

    For more information, see Aspect::Advice::Around.

  aspect
      aspect Singleton => 'Foo::new';

    The "aspect" declarator is used to enable complete reusable aspects.

    The first parameter to "aspect" identifies the aspect library class. If
    the parameter is a fully resolved class name (i.e. it contains double
    colons like Foo::Bar) the value it will be used directly. If it is a
    simple "Identifier" without colons then it will be interpreted as
    "Aspect::Library::Identifier".

    If the aspect class is not loaded, it will be loaded for you and
    validated as being a subclass of "Aspect::Library".

    And further paramters will be passed on to the constructor for that
    class. See the documentation for each class for more information on the
    appropriate parameters for that class.

    As with each individual advice type complete aspects can be defined
    globally by using "aspect" in void context, or lexically via a guard
    object by calling "aspect" in scalar context.

      # Break on the topmost call to function for a limited time
      SCOPE: {
          my $break = aspect Breakpoint => call 'My::foo' & highest;
          
      do_something();
      }

    For more information on writing reusable aspects, see Aspect::Library.

OPERATORS
  Pointcut &
    Overloading of bitwise "&" for pointcut declarations allows a natural
    looking boolean "and" logic for pointcuts. When using the "&" operator
    the combined pointcut expression will match if all pointcut
    subexpressions match.

    In the original Java AspectJ framework, the subexpressions are
    considered to be a union without an inherent order at all. In Perl you
    may treat them as ordered since they are ordered internally, but since
    all subexpressions run anyway you should probably not do anything that
    relies on this order. The optimiser may do interesting things with order
    in future, or we may move to an unordered implementation.

    For more information, see Aspect::Pointcut::And.

  Pointcut |
    Overloading of bitwise "|" for pointcut declarations allows a natural
    looking boolean "or" logic for pointcuts. When using the "|" operator
    the combined pointcut expression will match if either pointcut
    subexpressions match.

    The subexpressions are ostensibly considered without any inherent order,
    and you should treat them that way when you can. However, they are
    internally ordered and shortcutting will be applied as per normal Perl
    expressions. So for speed reasons, you may with to put cheap pointcut
    declarators before expensive ones where you can.

    The optimiser may do interesting things with order in future, or we may
    move to an unordered implementation. So as a general rule, avoid things
    that require order while using order to optimise where you can.

    For more information, see Aspect::Pointcut::Or.

  Pointcut !
    Overload of negation "!" for pointcut declarations allows a natural
    looking boolean "not" logic for pointcuts. When using the "!" operator
    the resulting pointcut expression will match if the single subexpression
    does not match.

    For more information, see Aspect::Pointcut::Not.

ADVICE CONTEXT METHODS
    The following methods are available in the advice code for one or more
    advice types. Different sets of methods are available for the different
    advice types.

    The actual objects involved are those within the Aspect::Point tree.

  type
    The "type" method is a convenience provided in the situation something
    has a Aspect::Point method and wants to know the advice declarator it is
    made for.

    Returns "before" for Aspect::Advice::Before advice, "after" for
    Aspect::Advice::After advice, or "around" for Aspect::Advice::Around
    advice.

LIBRARY
    The main Aspect distribution ships with the following set of libraries.
    These are not necesarily recommended or the best on offer. The are
    shipped with Aspect for convenience, because they have no additional
    CPAN dependencies.

    Their purpose is summarised below, but see their own documentation for
    more information.

  Aspect::Library::Singleton
    Aspect::Library::Singleton can be used to convert an existing class to
    function as a singleton and return the same object for every constructor
    call.

  Aspect::Library::Breakpoint
    Aspect::Library::Breakpoint allows you to inject debugging breakpoints
    into a program using the full power and complexity of the "Aspect"
    pointcuts.

  Aspect::Library::Wormhole
    Aspect::Library::Wormhole is a tool for passing objects down a call
    flow, without adding extra arguments to the frames between the source
    and the target, letting a function implicit context.

  Aspect::Library::Listenable
    Aspect::Library::Listenable assysts in the implementation of the
    "Listenable" design pattern. It lets you define a function as emitting
    events that can be registed for by subscribers, and then add/remove
    subscribers for these events over time.

    When the functions that are listenable are called, registered
    subscribers will be notified. This lets you build a general event
    subscription system for your program. This could be as part of a plugin
    API or just for your own convenience.

INTERNALS
    Due to the dynamic nature of Perl, there is no need for processing of
    source or byte code, as required in the Java and .NET worlds.

    The implementation is conceptually very simple: when you create advice,
    its pointcut is matched to find every sub defined in the symbol table
    that might match against the pointcut (potentially subject to further
    runtime conditions).

    Those that match, will get a special wrapper installed. The wrapper only
    executes if, during run-time, a compiled context test for the pointcut
    returns true.

    The wrapper code creates an advice context, and gives it to the advice
    code.

    Most of the complexity comes from the extensive optimisation that is
    used to reduce the impact of both weaving of the advice and the run-time
    costs of the wrappers added to your code.

    Some pointcuts like "call" are static and their full effect is known at
    weave time, so the compiled run-time function can be optimised away
    entirely.

    Some pointcuts like "cflow" are dynamic, so they are not used to select
    the functions to hook, but impose a run-time cost to determine whether
    or not they match.

    To make this process faster, when the advice is installed, the pointcut
    will not use itself directly for the compiled run-time function but will
    additionally generate a "curried" (optimised) version of itself.

    This curried version uses the fact that the run-time check will only be
    called if it matches the "call" pointcut pattern, and so no "call"
    pointcuts needed to be tested at run-time unless they are in deep and
    complex nested coolean logic. It also handles collapsing any boolean
    logic impacted by the safe removal of the "call" pointcuts.

    Further, where possible the pointcuts will be expressed as Perl source
    (including logic operators) and compiled into a single Perl expression.
    This not only massively reduces the number of functions to be called,
    but allows further optimisation of the pointcut by the opcode optimiser
    in perl itself.

    If you use only "call" pointcuts (alone or in boolean combinations) the
    currying results in a null test (the pointcut is optimised away
    entirely) and so the need to make a run-time point test will be removed
    altogether from the generated advice hooks, reducing call overheads
    significantly.

    If your pointcut does not have any static conditions (i.e. "call") then
    the wrapper code will need to be installed into every function on the
    symbol table. This is highly discouraged and liable to result in hooks
    on unusual functions and unwanted side effects, potentially breaking
    your program.

LIMITATIONS
  Inheritance Support
    Support for inheritance is lacking. Consider the following two classes:

      package Automobile;
      
  sub compute_mileage {
          # ...
      }
      
  package Van;
      
  use base 'Automobile';

    And the following two advice:

      before {
          print "Automobile!\n";
      } call 'Automobile::compute_mileage';
      
  before {
          print "Van!\n";
      } call 'Van::compute_mileage';

    Some join points one would expect to be matched by the call pointcuts
    above, do not:

      $automobile = Automobile->new;
      $van = Van->new;
      $automobile->compute_mileage; # Automobile!
      $van->compute_mileage;        # Automobile!, should also print Van!

    "Van!" will never be printed. This happens because Aspect installs
    advice code on symbol table entries. "Van::compute_mileage" does not
    have one, so nothing happens. Until this is solved, you have to do the
    thinking about inheritance yourself.

  Performance
    You may find it very easy to shoot yourself in the foot with this
    module. Consider this advice:

      # Do not do this!
      before {
          print $_->sub_name;
      } cflow 'MyApp::Company::make_report';

    The advice code will be installed on every sub loaded. The advice code
    will only run when in the specified call flow, which is the correct
    behavior, but it will be *installed* on every sub in the system. This
    can be extremely slow because the run-time cost of checking "cflow" will
    occur on every single function called in your program.

    It happens because the "cflow" pointcut matches *all* subs during
    weave-time. It matches the correct sub during run-time. The solution is
    to narrow the pointcut:

      # Much better
      before {
          print $_->sub_name;
      } call qr/^MyApp::/
      & cflow 'MyApp::Company::make_report';

TO DO
    There are a many things that could be added, if people have an interest
    in contributing to the project.

  Documentation
    * cookbook

    * tutorial

    * example of refactoring a useful CPAN module using aspects

  Pointcuts
    * New pointcuts: execution, cflowbelow, within, advice, calledby. Sure
    you can implement them today with Perl treachery, but it is too much
    work.

    * We need a way to match subs with an attribute, attributes::get() will
    currently not work.

    * isa() support for method pointcuts as Gaal Yahas suggested: match
    methods on class hierarchies without callbacks

    * Perl join points: phasic- BEGIN/INIT/CHECK/END

  Weaving
    * The current optimation has gone as far as it can, next we need to look
    into XS acceleration and byte code manipulation with B:: modules.

    * A debug flag to print out subs that were matched during weaving

    * Warnings when over 1000 methods wrapped

    * Allow finer control of advice execution order

    * Centralised hooking in wrappers so that each successive advice won't
    need to wrap around the previous one.

    * Allow lexical aspects to be safely removed completely, rather than
    being left in place and disabled as in the current implementation.

SUPPORT
    Please report any bugs or feature requests through the web interface at
    <http://rt.cpan.org/Public/Dist/Display.html?Name=Aspect>.

INSTALLATION
    See perlmodinstall for information and options on installing Perl
    modules.

AVAILABILITY
    The latest version of this module is available from the Comprehensive
    Perl Archive Network (CPAN). Visit <http://www.perl.com/CPAN/> to find a
    CPAN site near you. Or see <http://search.cpan.org/perldoc?Aspect>.

AUTHORS
    Adam Kennedy <adamk@cpan.org>

    Marcel GrĂ¼nauer <marcel@cpan.org>

    Ran Eilam <eilara@cpan.org>

SEE ALSO
    You can find AOP examples in the "examples/" directory of the
    distribution.

    Aspect::Library::Memoize

    Aspect::Library::Profiler

    Aspect::Library::Trace

COPYRIGHT
    Copyright 2001 by Marcel GrĂ¼nauer

    Some parts copyright 2009 - 2011 Adam Kennedy.

    This library is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.