Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [aspectj-users] How to provide external pcd definition?

Wow. This is gold.

I had this exact discussion with someone at the symposium. They needed a way
to dynamically configure pointcuts in this manner. They even wanted to be
able to build up the pointcut expression. 

So, instead of:

         <property name="pointcutExpression">
            execution(* *(..)) && this(Foo)
         </property>

They wanted to run some logic to generate the expression.

Sure this isn't efficient.... But it would be fantastic for the cases which
need this.

Dion


> -----Original Message-----
> From: aspectj-users-admin@xxxxxxxxxxx 
> [mailto:aspectj-users-admin@xxxxxxxxxxx] On Behalf Of Adrian Colyer
> Sent: Tuesday, May 11, 2004 4:50 PM
> To: aspectj-users@xxxxxxxxxxx
> Cc: rod.johnson@xxxxxxxxxxxxxxx
> Subject: Re: [aspectj-users] How to provide external pcd definition?
> 
> This question has been vexing me for the last few days. Any 
> configuration of a pointcut would have to go through the 
> AspectJ compiler, so what you're currently doing is about as 
> good as it can get right now. 
> 
> You could imagine an XML syntax that gets turned into an 
> aspect by some build step, e.g.
> 
> <aspect name="DatabaseTestAspect" extends=" 
> AbstractDatabaseTestAspect">
>   <pointcut 
> name="applicationCode">within(patterntesting..*)</pointcut>
>   <pointcut name="allowedCode">within(patterntesting.db..*)</pointcut>
> </aspect>
> 
> (just for illustration, not a real syntax)
> 
> but is that really so much easier to understand than:
> 
> aspect DatabaseTestAspect extends AbstractDatabaseTestAspect {
>   pointcut applicationCode() : within(patterntesting..*);
>   pointcut allowedCode() : within(patterntesting.db..*); }
> 
> ? Especially when you've still got to pass the result through 
> the compiler anyway.
> 
> I've been talking a lot with the Spring folks at the TSS 
> Symposium, and I can see a case for wanting true runtime 
> configuration of pointcut values for some infrastructure 
> (auxiliary) aspects - the kind of things that the J2EE 
> community is very used to specifying in config files rather 
> than in code. One of the exciting things that came out of 
> those discussions is a way to use Spring's IoC capabilities 
> to configure aspects (more on that soon), but this capability 
> doesn't extend to configuring pointcuts (just things like the 
> DataSource for a persistence aspect to use etc.). I wanted to 
> enable pointcut configuration in the same way, so I've built 
> a private prototype today that shows one way it could be 
> done. Here's how it looks, and I'd be interested in feedback 
> as to whether others would find this
> useful:
> 
> Firstly, a new utility class: JoinPointMatcher.  
> JoinPointMatcher is constructed with a string (in the 
> expected usage this is obtained from a config file, but it 
> could be generated in the program itself at runtime for 
> extreme use cases) which contains an AspectJ pointcut expression,
> e.g.:
> 
> JoinPointMatcher jpm = new 
> JoinPointMatcher("within(patterntesting..*)");
> 
> At any join point, you can ask JoinPointMatcher whether or 
> not it matches: 
>  if( jpm.matches(thisJoinPoint)) ...
> 
> Here's an aspect that allows runtime configuration using this 
> mechanism:
> 
> aspect DynamicPointcutConstructionExample {
> 
>   private static JoinPointMatcher jpm;
> 
>   public void setPointcutExpression(String pointcutExpr) {
>     jpm = new JoinPointMatcher(pointcutExpr);
>   }
> 
>   // this pointcut is used to narrow down as far as possible 
> at compile time the set of places
>   // at which a dynamic pointcut could match (for efficiency)
>   pointcut scope() : within(org.xyz.foo); 
> 
>  before() : scope() && if(jpm.matches(thisJoinPoint)) {
>     System.out.println("I matched!!");
>  }
>  
> }
> 
> The consequence you pay for using dynamic pointcuts (I'm 
> using the word dynamic in analogy to the use of "dynamic" in 
> DII, it may not be the best
> term) is that the pointcut matching is (very much) less 
> efficient since the jpm.match code is driven for every join 
> point in the scope (whereas the same pointcut specified at 
> compile time would cause the advice to execute exactly where 
> it needs to with no additional overhead or redundancy). If a 
> dynamic pointcut proved to be too slow, you could always 
> switch back to a traditional statically specified pc. 
> 
> If you're using Spring with the above example, you can 
> configure the aspect with e.g.
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
> "http://www.springframework.org/dtd/spring-beans.dtd";>
> <beans>
>     <!-- what follows is an example syntax for specifying a 
> factoryMethod, 
> 
>          I hope we end up with something very close to this 
> in Spring -->
>     <bean id="dynamicPointcutConstructionExample" 
>           class="DynamicPointcutConstructionExample" 
>           factoryMethod="aspectOf">
>         <property name="pointcutExpression">
>            execution(* *(..)) && this(Foo)
>         </property>
>     </bean>
> </beans>
> 
> Spring will set the value of the pointcutExpression attribute 
> when the aspect is constructed. Many thanks are due to Rod 
> Johnson for the inspiration to look into this.
> 
> [For the AspectJ developers, here's how the prototype 
> currently works: 
> 
> JoinPointMatcher uses the PatternParser class to build a 
> Pointcut (simple).
> 
> I then added a new match method in the Pointcut hierarchy 
> that takes a JoinPoint instead of a shadow, and implemented 
> match(JoinPoint) down the hierarchy to do the right thing. I 
> had to add match(Class) methods to TypePatterns too. All the 
> changes were self-contained, and the logic mirrors the 
> matching logic for shadows.
> 
> Restrictions in the implementation are that you can't use 
> cflow or cflowbelow in a dynamic pointcut (matching is done 
> solely on the current join point), you can't use if() (don't 
> want to go off into code), and you can't provide context 
> information (bind "this(foo)" to a parameter "foo") or refer 
> to other pointcuts.
> 
> Essentially I've written a convenience class for writing a 
> powerful form of if() pcds.
> ]
> 
> Love it? Hate it? Let me know...
> 
> Cheers, Adrian.
> 
> I know, I know, I digressed for a day - Back to 1.2rc2 and 
> AJDT tomorrow....
> 
> -- Adrian
> Adrian_Colyer@xxxxxxxxxx
> 
> aspectj-users-admin@xxxxxxxxxxx wrote on 07/05/2004 09:17:35:
> 
> > Hi,
> > 
> > On the Pattern Testing project 
> (http://patterntesting.sf.net), we have 
> > aspects that enforce some design rules. For example:
> > 
> > public abstract aspect AbstractDatabaseTestAspect {
> >     /**
> >      * Specify what is application code that should be 
> subject to the
> >      * pattern test.
> >      * 
> >      * Ex: <code>pointcut applicationCode():
> > within(patterntesting.*)</code>
> >      */
> >     public abstract pointcut applicationCode();
> > 
> >     /**
> >      * Specify which classes are allowed to call JDBC.
> >      */
> >     public abstract pointcut allowedCode();
> > 
> >     /**
> >      * Specify which JDBC calls are forbidden.
> >      */
> >     pointcut forbiddenCalls() :
> >         call(public * java.sql..*(..)) ||
> >         call(public * javax.sql..*(..));
> > 
> >     /**
> >      * Raise error if violations found.
> >      */
> >     declare error: (applicationCode() && forbiddenCalls()) &&
> > !allowedCode() :
> >         "It is not allowed to use the JDBC API from here"; }
> > 
> > Now, the question is: How can we make the applicationCode and 
> > allowedCode pointcuts configurable by the end users?
> > 
> > Of course one solution is to have create classes that extend the 
> > abstract aspect. However that sounds complex when compared 
> to simple 
> > configuration data (the end users would need to create a 
> project where 
> > to put the code, etc).
> > 
> > Any idea?
> > 
> > Note: The solution we're using so far (but which I don't 
> like because 
> > it's tied to the build system) is to use Ant filters:
> > 
> > public aspect DatabaseTestAspect extends 
> AbstractDatabaseTestAspect {
> >     public pointcut applicationCode() :
> >         @maven.patterntesting.suite.java.database.applicationCode@;
> >     public pointcut allowedCode() :
> >         @maven.patterntesting.suite.java.database.allowedCode@;
> > }
> > 
> > Thanks
> > -Vincent
> > 
> > _______________________________________________
> > aspectj-users mailing list
> > aspectj-users@xxxxxxxxxxx
> > http://dev.eclipse.org/mailman/listinfo/aspectj-users
> 
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-users
> 
> 



Back to the top