Announcement Announcement Module
Collapse
No announcement yet.
Hooking into Spring weaving Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Hooking into Spring weaving

    I am wondering if it is possible to hook into springs weaving instead of creating another proxy when using AOP?

    Here is a simple example:

    Code:
    (at)Transactional
    (at)Lockable 
    public void save() {}
    By default, this will create two proxies. Spring will create one for (at)Transactional, and my BeanPostProcessor will create another one for
    my custom (at)Lockable interface.

    Is it somehow possible to "hook" into the weaving process of spring and add my custom Advice to the same ProxyFactory that is used for the (at)Transactional annotation?

    If not, is there any "best practices" for minimizing the number of proxies created?

    I do NOT want to use aspectJ expressions.

    Kind regards

    /johan

  • #2
    The best practice is the one you don't want to use.

    I suggest you check the code for how spring does it. You can simply check the type of the bean if it already is a proxy (i.e. object implementing Advised) then you can simply add the interceptor/advice adding your behavior.

    Comment


    • #3
      Aha, well if the proxy implements Advised it could work. However, I see a few problems...
      1. Ordering of advises will be difficult
      2. Is it possible to access any annotations set on the class, not the interface?

      Comment


      • #4
        This will of course not be a problem since I have access to the target.
        Originally posted by johras View Post
        2. Is it possible to access any annotations set on the class, not the interface?
        The reason I want to try this out since I want type-safety and pure java refactoring to work for my pointcuts.

        Comment


        • #5
          If that is the reason not to use AspectJ.... With AspectJ you can have all that also...

          Also if your Advice implements Ordered there isn't an issue either, also the ordering of your Bean(Factory)PostProcessor is taken into account.

          Comment


          • #6
            You are right... this is really good. Seems lite everything is in place then.

            <tx:annotation-driven order="1"/>
            And my custom advice to a higher or lower order depending on what I want.

            However, if aspectj expressions are best practice and I get them to be typesafe and refactoring friendly that sounds good but could you please point me in the right direction here.

            For me, "@annotation(MyCustomAnnotation)" is neither? Even if it is much better than using scary execution pointcuts...

            Comment


            • #7
              Why is the execution pointcut scary?! You can use your own annotation for matching (I.e. the @Lockable)...

              Code:
              <aop:pointcut expression="execution(* (@Lockable *..*.*(..)))" />
              You can even bind it to a variable if you want.

              Code:
              public Object aroundLockable(ProceedingJoinPoint pjp,Object target, Lockable lock) {
                // do your stuff.
                Object retVal = pjp.proceed();
                return retVal;
              }
              Code:
              <bean id="myAspect" class="myAspectClass"/>
              
              <aop:config>
              <aop:pointcut id="lockableMethod" expression="execution(* (@Lockable *..*.*(..)) and target(target) and annotation(lock)" />
              <aop:aspect ref="myAspect">
                <aop:around pointcut-ref="lockableMethod" method="aroundLockable" />
              </aop:aspect>
              </aop:config>
              Ofcourse you can do the same with @Aspect or the AspectJ language instead of in XML.

              Comment


              • #8
                I meant examples like "execution (* *..services.*.save(..)" are scary since
                since the expression is a string and it will not be changed if I change my method to
                saveAndUpdate(). The same goes for changing an annotation name regardless if I am using @annoation or execution, changing the name of the annotation does not change my pointcuts.

                Using springs AnnotationMatchingPointcut however solves this. I can also easily find my pointcuts by following references to the annotation in my IDE. I feel more confident that my pointcuts will always work since I should get a compiler error if the annotation does not match and I do not have to rely so heavily on tests to prove that my advices are executed when expected.

                Comment


                • #9
                  Again with proper tooling your statement isn't true. If you use eclipse and the AJDT. Then you will get all that if you use @Aspects or aspectj languague. And it gives you more control and easy of use then messing around with all the pre aspectj stuff..

                  Also if you write your pointcut correct (and you should at least write 1 test case!) and you messup your test fails...
                  Last edited by Marten Deinum; Oct 7th, 2008, 02:43 AM.

                  Comment


                  • #10
                    Thanks, your input is very appreciated!

                    I agree that it would be much easier to use @Aspect annotation on my advice and in our project it could probably work especially since we are using a minimal number of pointcuts. A also agree that it is a bit "messy" to solve it the way I want it and it may not be the best possible solution in the long run.

                    BUT... perhaps I get get more control and easy of use using aspectJ expressions, I would still feel more confident with:
                    Code:
                    @Aspect
                    public void MyClass {
                        @AnnotationMatchingPointcut(MyCustomAdvice.class)
                        public void method() {}
                    over:
                    Code:
                    @Aspect
                    public void MyClass {
                        @Pointcut("@annotation(MyCustomAdvice")
                        public void method() {}
                    Kind regards

                    /johan

                    Comment


                    • #11
                      Originally posted by johras View Post
                      Code:
                      @Aspect
                      public void MyClass {
                          @AnnotationMatchingPointcut(MyCustomAdvice.class)
                          public void method() {}
                      over:
                      Code:
                      @Aspect
                      public void MyClass {
                          @Pointcut("@annotation(MyCustomAdvice")
                          public void method() {}
                      This thread has caught my attention because I have written a couple of aspects that are based on custom annotations. I am intrigued by @AnnotationMatchingPointcut. Unfortunately, AnnotationMatchingPointcut is NOT an annotation. You can't use it that way. I just tried, out of freak hope that it would work, and Eclipse is puking all over that. It appears you can res it up inside an appContext.xml file, but I don't see how to plug it in to @AspectJ.

                      So far, I have
                      Code:
                       	@Around("execution(@my.package.app.annotations.Timed * *(..))")
                      	public Object calculatePerformance(ProceedingJoinPoint jp) throws Throwable {
                      And yes, I have a unit test to make sure my aspect works and that my point cut works.

                      Comment


                      • #12
                        Sorry if I was not clear, I did not mean that I am doing that, I meant that
                        I would like it to work that way.

                        If it worked, it world mean the world to me ;-)
                        Since it does not work (and thats reason for this thread), I have been testing to do some stuff with Springs AOP support using a custom BeanPostProcessor to advice my classes which actually works ok but you donīt get it out of the box.

                        Using @Aspect, i think your approach is the the one to use, or ("@annotation(my.package.app.annotations.Timed) " ).
                        Last edited by johras; Oct 7th, 2008, 01:02 PM.

                        Comment

                        Working...
                        X