Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-dev] using classes for pointcut libraries

Wes,

This is marvelous! It's a great suggestion for allowing configuration of aspect libraries. Taking advantage of the fact that classes can have PCD's and can be extended is very nice. You have to like solutions that use existing language features. Kudos!!

We should try out this approach to define a generic J2EE pointcut library, with app-server specific extensions.

I think extensible pointcuts would still be valuable for configuration purposes, so that you can use a given library aspect in a system that is composed of multiple components properly. I don't believe the approach you outlined would work because it has to weave the aspects that use the library for each component. At run time, one of these aspect "classes" would be loaded, and the other components will make calls on incorrect or missing methods from their "version" of the aspect... You implied this issue by pointing out how to tailor the aspects to a fixed number of different clients.

I also find having an aspect extend a class to be a bit questionable. It seems odd, though I see why it works.

Ron

Ron Bodkin
Chief Technology Officer
New Aspects of Security
m: (415) 509-2895

> ------------Original Message-------------
> From: Wes Isberg <wes@xxxxxxxxxxxxxx>
> To: "aspectj-dev@xxxxxxxxxxx" <aspectj-dev@xxxxxxxxxxx>
> Date: Tue, Jul-29-2003 7:20 PM
> Subject: [aspectj-dev] using classes for pointcut libraries
> 
> This is a pattern to use concrete pointcuts in classes
> and inheritance to achieve some of the effects Adrian
> wants in interface pointcuts.  It's similar to what
> I suggested wrt abstract aspects, but is a bit
> more modular and less constraining.
> 
> ----
> class PrivateLibrary {
>     public pointcut pc() : {definition};
> }
> 
> // perhaps "final class.."
> public class Library extends PrivateLibrary {}
> 
> aspect Client {
>      before() : Library.pc() { ... }
> }
> 
> aspect Deployer {
>      declare parents: Library extends MyLibrary;
>      static class MyLibrary extends PrivateLibrary {
>          public pointcut pc() : {re-definition};
>      }
> }
> ----
> Effects:
> 
> - Clients refer to library pointcuts
> 
> - A deployer can select from available implementations
>    and affect all clients of the library.  Conservatively,
>    this requires reweaving the clients.
> 
> - Different clients can be made to refer to different
>    implementations, depending on the kind of reference
>    they make.
> 
> The code below shows you can use the current scope as an
> implicit class reference for the pointcut.  Because
> this scope can be changed using inter-type declarations
> of parent class, you can specify implementations and
> affect clients differently, depending on the path used
> to resolve their reference to a pointcut.  The same
> effect holds for clients that use explicit class
> references if the referent member is found by
> searching the supertypes rather than directly
> in the referent supertype.
> 
> Some drawbacks:
> - single-inheritance: obviously, using a class in Java
> limits one's ability to re-use by inheritance.  But I
> suspect most uses should be via explicit class reference
> rather than inheritance.  (Indeed, some e.g., Bloch think
> it bad style to use interfaces to simplify references
> to constants; see next.)
> 
> One way to require clients use explicit references is
> to to mark a pointcut library class final.  However, that
> prevents there being two or more implementations in the
> same namespace.  If developers want to be able to
> have different pointcuts for different clients, they
> can instead make client-specific library subtypes
> that can be targetted for reimplementation.
> 
> ----
> ...
> public class Library extends PrivateLibrary {}
> 
> public class AppLibrary extends Library {}
> public class BeanLibrary extends Library {}
> 
> aspect ClientOne {
>      before() : AppLibrary.pc() { ... }
> }
> 
> aspect ClientTwo {
>      before() : BeanLibrary.pc() { ... }
> }
> 
> aspect Deployer {
>      declare parents: BeanLibrary extends MyBeanLibrary;
>      declare parents: AppLibrary extends MyAppLibrary;
>      ...
> }
> ----
> 
> To some, a more natural way to acknowledge that there
> is a search through supertypes for a referent might
> be to use inheritance and unqualified references:
> 
> ----
> aspect BeanClient extends BeanLibrary {
>      before() : pc() { ... }
> }
> ----
> 
> - Style: using pointcuts is like using static methods.
> Some consider it poor style to use unqualified
> references to static members or to use static subtype
> references to refer to supertype members. I agree with
> this style point in regular Java code, but it's not
> enough to convince me not to use this idiom.  For
> extensible pointcuts, we do need to change the referent,
> but at compile/weave time, not at runtime. (Dynamic
> aspects would be nice in many ways, but this ain't
> that.)  This is better than interface pointcuts in
> that they don't lead people to believe it is
> something like method polymorphism based on the
> executing instance.  (The way to do that in AspectJ
> is to have different subaspects of an abstract
> aspect.)
> 
> One advantage of using classes rather than abstract
> aspects is that it's clear the pointcuts are defined
> and there is no associated behavior or state, as there
> might be when inheriting from an abstract aspect. It's
> also not as constraining, since you can inherit from
> classes in more places than you can from abstract
> aspects.  And I personally believe it is better than
> using interfaces for abstract pointcuts.  I would
> support interfaces if the pointcut definitions
> varied at runtime based on the instance, assuming
> that wouldn't prevent good compiler-based
> implementations of AspectJ.
> 
> If this survives scrutiny, I'll toss it in with
> the sample code.
> 
> Wes
> 
> (btw, this suggests that the algorithm for incremental
> compilation needs to consider changes anywhere in the
> aspect type hierarchy or to the type hierarchy of a
> pointcut referent.  I'm also assuming/hoping that
> weaving binaries has the same effect as compiling
> wrt the pointcut selected by searching up the type
> hierarchy.)
> 
> Here's some test code.  This will NOT work in 1.1.0
> because of the bug with named pointcuts using cflow,
> but does work using the compiler in the current tree.
> 
> ----------- lib/PointcutLibraryTest.java
> 
> package lib;
> 
> public class PointcutLibraryTest {
>      public static void main(String[] a) {
>          new Test().run();
>      }
> }
> 
> class Test {
>      public Test() {}
>      public void run(){ prun(); }
>      private void prun() {
>          System.out.println("Test.prun()");
>      }
> }
> 
> /** private default implementation of library */
> class PrivatePointcutLibrary {
>      pointcut adviceCflow() : cflow(adviceexecution());
>      pointcut publicCalls() : call(public * *(..))
>          && !adviceCflow()
>          ;
> }
> 
> /** public interface for library */
> class PointcutLibrary extends PrivatePointcutLibrary {
> }
> 
> // ---- different clients of the library
> 
> /** use library by inheriting scope in aspect */
> aspect AEL extends PointcutLibrary {
>      before() : publicCalls() {
>          System.out.println("AEL: "
>              + thisJoinPointStaticPart);
>      }
> }
> 
> /** use library by inheriting scope in class */
> class CEL extends PointcutLibrary {
>      static aspect A {
>          before() : publicCalls() {
>              System.out.println("CEL: "
>                  + thisJoinPointStaticPart);
>          }
>      }
> }
> 
> /** more clients by inheritance */
> aspect CELSubAspect extends CEL {
>      before() : publicCalls() {
>          System.out.println("CSA: "
>              + thisJoinPointStaticPart);
>      }
> }
> 
> 
> 
> /** client by external reference to library */
> aspect ExternalClientOfLibrary {
>    before() : PointcutLibrary.publicCalls() {
>        System.out.println("XCL: "
>            + thisJoinPointStaticPart);
>    }
> }
> 
> // ---- redefining library pointcuts
> 
> //-- affect all clients of PointcutLibrary
> // test: XCL advises Test()
> class VendorPointcutLibrary extends PrivatePointcutLibrary {
>      /** add calls to public constructors */
>      pointcut publicCalls() : PrivatePointcutLibrary.publicCalls()
>          || (call(public new(..)) && !adviceCflow());
>      static aspect A {
>          declare parents:
>              PointcutLibrary extends VendorPointcutLibrary;
>      }
> }
> 
> //-- only affect CEL, subtypes, & references thereto
> // test: CSA does not advise call(void println(String))
> // test: CSA advises call(void prun())
> class CPlus extends PointcutLibrary {
>      /** add calls to private methods, remove calls to java..* */
>      pointcut publicCalls() : (PointcutLibrary.publicCalls()
>          || (call(private * *(..)) && !adviceCflow()))
>          && (!(call(* java..*.*(..)) || call(java..*.new(..))));
>      static aspect A {
>          declare parents: CEL extends CPlus;
>      }
> }
> 
> 
> 
> 
> _______________________________________________
> aspectj-dev mailing list
> aspectj-dev@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-dev
> 


Back to the top