Announcement Announcement Module
Collapse
No announcement yet.
Injecting non-Spring beans & Spring AOP not work together? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Injecting non-Spring beans & Spring AOP not work together?

    Dear all,

    I'm a greenhorn in Spring, and reading the book of Spring in Action 2nd Edition now. I got following problem when following the examples in the book and attempting to mix injecting non-Spring beans with normal Spring AOP features. Related chapters in the book are 3.3 and 4.3.

    Source codes & configurations are (some simple classes are omitted):

    1. I defined Magician class as following. Please note in order o make injecting non-Spring beans work, the annotation is added:



    Code:
    import org.springframework.beans.factory.annotation.Configurable;
    @Configurable("lisa")
    public class Magician implements Performer
    {
        private String magicWords;
        private MagicBox magicBox;
    
        public void perform()
        {
            System.out.println(magicWords);
            System.out.println("The magic box contains...");
            
            System.out.println(magicBox.getContents());
        }
    
        public void setMagicWords(String magicWords)
        {
            this.magicWords = magicWords;
        }
    
        public void setMagicBox(MagicBox magicBox)
        {
            this.magicBox = magicBox;
        }
    }
    2. The MagicBox implementation class is:

    Code:
    public class MagicBoxImpl implements MagicBox
    {
        public String getContents()
        {
            return "A beautiful assistant";
        }
    }
    3. Audience class for the aspect is:

    Code:
    public class Audience
    {
        public void takeSeats()
        {
            System.out.println("The audience is taking their seats.");
        }
        
        public void turnOffCellPhones()
        {
            System.out.println("The audience is turning off their cell phones.");
        }
        
        public void applaud()
        {
            System.out.println("CLAP CLAP CLAP CLAP");
        }
        
        public void demandRefund()
        {
            System.out.println("Boo! We want our money back!");
        }
    }
    4. Configurations are:

    HTML Code:
    	<bean id="magicBox" class="com.springinaction.springidol.MagicBoxImpl">
    	</bean>
    
    	<bean id="audience" class="com.springinaction.springidol.Audience"/>
    
        <aop:config>  
             <aop:aspect ref="audience">  
                 <aop:pointcut id="performance" expression="execution(* *.perform(..))"/>  
                 <aop:before method="takeSeats" pointcut-ref="performance"/>  
                 <aop:before method="turnOffCellPhones" pointcut-ref="performance"/>  
                 <aop:after-returning method="applaud" pointcut-ref="performance"/>  
                 <aop:after-throwing method="demandRefund" pointcut-ref="performance"/>  
             </aop:aspect>  
        </aop:config> 
    
    	<bean id="harry" class="com.springinaction.springidol.Magician">
    		<property name="magicBox" ref="magicBox"/>
    		<property name="magicWords" value="Bippity Boppity boo"/>
    	</bean>
    	
    	<context:spring-configured/>
    	<bean id="lisa" class="com.springinaction.springidol.Magician" abstract="true">
    		<property name="magicBox" ref="magicBox"/>
    		<property name="magicWords" value="O ma ni ma mi hong"/>
    	</bean>
    5. Test codes are:

    Code:
            ApplicationContext context = new ClassPathXmlApplicationContext("com/springinaction/springidol/springidol.xml");
    
            Performer harry = (Performer) context.getBean("harry");
            harry.perform();
            
            // New a bean outside spring
            Performer lisa = new Magician();
            lisa.perform();
    And I run the codes with following VM argument:

    Code:
    -javaagent:path\lib\aspectj\aspectjweaver.jar
    Before applying the aop, both harry & lisa work perfectly well. However, after I added aop configurations, I got following output:

    Code:
    The audience is taking their seats.
    The audience is turning off their cell phones.
    Bippity Boppity boo
    The magic box contains...
    A beautiful assistant
    CLAP CLAP CLAP CLAP
    Exception in thread "main" java.lang.IllegalStateException: Post-processor tried to replace bean instance of type [com.springinaction.springidol.Magician] with (proxy) object of type [$Proxy5] - not supported for aspect-configured classes!
    	at org.springframework.beans.factory.wiring.BeanConfigurerSupport.checkExposedObject(BeanConfigurerSupport.java:174)
    	at org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:147)
    	at org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:59)
    	at org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(AbstractDependencyInjectionAspect.aj:89)
    	at com.springinaction.springidol.Magician.<init>(Magician.java:6)
    	at com.springinaction.springidol.MagicianApp.main(MagicianApp.java:25)
    As you can see, harry still works but error happens at
    Code:
            Performer lisa = new Magician();
    I also noticed that if I move the section starting with
    HTML Code:
    <context:spring-configured/>
    to the position before the definition of harry, then even harry cannot work.

    Could anybody enlighten me on this. Thank you!
    Last edited by vichyboy; Jun 27th, 2009, 02:25 AM. Reason: Corrected mistakes and added more explanation

  • #2
    Hi vichyboy,

    I'm stucked in the same issue.
    I wondered if you were able to tell me if get it working and how.
    I have been reading this thread http://forum.springsource.org/showthread.php?p=125314 and the prevoius to it but didn't get it.

    kind regards

    Comment


    • #3
      Hi Polaco,

      I'm sorry, I was learning Spring last year while I was facing this problem. As nobody answered me and it's not a major issue, I didn't spend more time investigating.

      I guess the reason is that there is some limitation with Spring in terms of this: it can intercept the new operation and does necessary injection for you, but cannot replace the aspect-configured class object with the proxy during runtime. Not sure if I'm correct or not :-p

      Comment


      • #4
        Hi vichyboy,
        Thanks for replying. It seems also to me that is some Spring AOP - AspectJ problem, I am on the same situation you were last year, learning spring with Spring in Action book.
        I guess I will go ahead and then maybe return to this issue when I have make some experience.

        kind regards

        Comment


        • #5
          I read the posts you mentioned and there is an answer already I think:

          http://forum.springsource.org/showthread.php?t=38289

          Cite from ramnivas:

          To summarize: Spring AOP works only with beans created by application context (or by programmatic proxy creation). If you want your aspect to be applied to beans created outside the application context, you must weave using AspectJ weaver (compile-time or load-time).

          Comment


          • #6
            I see, but when you added this parameter to the jvm
            -javaagent: path\lib\aspectj\aspectjweaver.jar
            seems like you are using a load time aspectJ weaver.
            So I don't understand if ramnivas is saying that you can't mix Spring AOP with AspectJ ones or that in order to do that use an aspectJ weaver, since aspects seems to be executed but the "Post-processor tried to replace bean instance" arises then.
            Last edited by Polaco; May 31st, 2010, 10:25 AM.

            Comment

            Working...
            X