Announcement Announcement Module
Collapse
No announcement yet.
Not able to get the aspects applied to domain objects Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Not able to get the aspects applied to domain objects

    I know there are innumerous threads on this but I still couldnt get the answers. So I am trying again.

    My problem: Not able to get the aspects applied to domain objects using load time weaving

    Environment:
    spring app context
    HTML Code:
      
    <beans
            xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:util="http://www.springframework.org/schema/util"
            xmlns:aop="http://www.springframework.org/schema/aop"
            xsi:schemaLocation="
        [url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.0.xsd[/url]
        [url]http://www.springframework.org/schema/util[/url] [url]http://www.springframework.org/schema/util/spring-util-2.0.xsd[/url]
        [url]http://www.springframework.org/schema/aop[/url] [url]http://www.springframework.org/schema/aop/spring-aop-2.0.xsd[/url]
        ">
        
        <aop:aspectj-autoproxy proxy-target-class="true"/>
        <bean id="myAspect" class="aspecttest.MannersAspectAnnotated"/>
        <bean id="testInjectionClass" class="aspecttest.TestInjectionClass"/>
        <aop:spring-configured/>
        
        </beans>
    MannersAspectAnnotated.java
    HTML Code:
    package aspecttest;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class MannersAspectAnnotated {
    
        @Pointcut("execution( public void *.HelloWorld.say*(..))")
        public void callToSayMethod(){}
        
        @Pointcut("execution( public static void *.HelloWorld.sayStatic(..))")
        public void callToSayStaticMethod(){}
        
        @Pointcut("execution( *void *.Hello*.sayToPerson(..)) &&  args(message, name)")
        public void callToSayToPersonMethod(String message, String name){}
        
        @Before("callToSayMethod()")
        public void adviceBeforeToSayMethod(){
            System.out.println("Good Morning from adviceBeforeToSayMethod");
        }    
        @Around(value="callToSayToPersonMethod(message,name)",argNames="message,name")
        public void aviceAroundSayToPersonMethod(ProceedingJoinPoint pjp, String message, String name) throws Throwable{
            pjp.proceed(new Object[]{message, name+"-san! from aviceAroundSayToPersonMethod"});
        }
        
        @After("callToSayStaticMethod()")
        public void adviceAfterToSayStaticMethod(){
            System.out.println("Bye! from adviceAfterToSayStaticMethod");
        }
        
        @After("callToSayMethod()")
        public void adviceAfterToSayMethod(){
            System.out.println("Bye! from adviceAfterToSayMethod");
        }
        
    }
    HelloWorld.java
    HTML Code:
    package aspecttest;
    
    import org.springframework.beans.factory.annotation.Autowire;
    import org.springframework.beans.factory.annotation.Configurable;
    
    // HelloWorld.java
    @Configurable(autowire=Autowire.BY_TYPE)
    public class HelloWorld {
        private testInjectionClass;
    
       public setTestInjectionClass(TestInjectionClass testInjectionClass){
    	this.testInjectionClass=testInjectionClass;
       }
        public void say(String message) {
            System.out.println(message);
        }
        
        public void sayToPerson(String message, String name) {
            System.out.println(name + ", " + message);
        }
        
        public static void sayStatic(String message) {
            System.out.println("Static "+message);
        }
    }
    aop.xml
    HTML Code:
    <!DOCTYPE aspectj PUBLIC    
      "-//AspectJ//DTD//EN"    "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">    
    
    <aspectj>   
      <weaver 
        options="-showWeaveInfo -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler">
        <include within="aspecttest.HelloWorld"/>
      </weaver>
      <aspects>
        <include within="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"/>
      </aspects> 
    </aspectj>
    java runtime argument
    HTML Code:
    -javaagent:/Users/kruttikagarwal/Downloads/spring-framework-2.0.8/lib/aspectj/aspectjweaver.jar
    Everything works, All depedency injections are fine. Its just that the aspects dont get applied when I do new HelloWorld().

    I tried going through the spring source code to understand the behavior. Not that I was very successful in my adventure but heres what i got and please correct me if I am wrong-
    When we instantiate using new operator the AbstractBeanConfigurerAspect's after returning advice gets called which calls BeanConfigurerSupport's configureBean method which in turn calls DefaultListableBeanFactory's autowireBeanProperties whcich autowires. So its fine uptill that, But since the bean was not created by AbstractAutowireCapableBeanFactory's createBean method(which is called to create beans in app context) the registered BeanPostProcessors are not called and hence the AnnotationAwareAspectJAutoProxyCreator is not called and hence no proxy is created and hence no aspect get applied to the newly generated object. If I have this right, then please tell me how to apply aspect in my domain objects using load time weaving. Should I extend AnnotationBeanConfigurerAspect and provide a seperate implementation of configureBean()?

  • #2
    There are a couple of thing I note:

    1. You are not including MannersAspectAnnotated in aop.xml's aspects section, which should look something like:
    Code:
    <aspects>
        <include name="aspecttest.MannersAspectAnnotated"/>
        <include within="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"/>
      </aspects>
    2. While not an immediate problem, soon you will run into an issue where aspect is not actually injected with anything. So add "factory-method="aspectOf" when defining bean for the MannersAspectAnnotated aspect.

    -Ramnivas

    Comment


    • #3
      I already added that section in aop.xml and it worked but it worked because aspectj weaver weaved the aspect into the domain objects. I was trying to get the aspects applied using spring AOP i.e using cglib proxies created by AnnotationAwareAspectJAutoProxyCreator. It might sound stupid to do that since including aspects in aop.xml works but the reason i wanted to do it through Spring AOP way was to be consistent with the aspect programming model in the application. Instead of having some aspects applied through spring proxies and some weaved using aspectj LTW, I would have liked to follow a consistent approach.

      Comment


      • #4
        Spring AOP affects only Spring beans. Any object created outside using straight 'new' (such as your domain objects) won't be be advised by it; for that, you must use AspectJ.

        -Ramnivas

        Comment


        • #5
          Thanks a lot for the reply ramniwas.

          Comment


          • #6
            I did a tutorial that uses @Configurable to configure your domain objects:

            http://amin-mc.blogspot.com/2008/02/...spring-25.html


            As Ramnivas mentioned if you want to apply AOP to your domain objects you need to use AspectJ, which is pretty straightforward to do.

            Comment

            Working...
            X