Announcement Announcement Module
Collapse
No announcement yet.
Strange problems with AOP Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Strange problems with AOP

    I am having some problems with using AOP in the case when the advice class is wired to the bean that is being advised. Below I will try to illustrate the problem on a simple example.

    I have a very simple bean that I want to be advised:

    Code:
    package somepackage;
    
    public class TestBean1 {
    	public void test1(){
    		System.out.println(this.getClass().getCanonicalName()+".test1() is called");
    	}
    }
    Here is my advice class:

    Code:
    package somepackage;
    
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    public class TestAspectJAdvice {
    	private TestBean1 testBean1;
    	public void setTestBean1(TestBean1 testBean1) {
    		this.testBean1 = testBean1;
    	}
    
    	public void advice1(){
    		System.out.println(this.getClass().getCanonicalName()+".advice1()");
    	}
    }
    As you can see, it contains a reference to the class TestBean1 that is being advised. Finally, here are my Spring configuration files:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">      
    	<bean id="testBeanFactory"
    		class="org.springframework.context.support.ClassPathXmlApplicationContext">
    		<constructor-arg>
    			<list>
    				<value>applicationContext-aopTest.xml</value>
    			</list>
    		</constructor-arg>
    	</bean>
    	
    </beans>
    and

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
    
    	<bean id="testBean1" class="somepackage.TestBean1">
    	</bean>
    	
    	<bean id="testAspectJAdvice" class="somepackage.TestAspectJAdvice">
    		<property name="testBean1" ref="testBean1"></property>
    	</bean>
    	
    	
    	<aop:config>
    		<aop:aspect ref="testAspectJAdvice" >
    			<aop:before method="advice1" 
    				pointcut="execution(* *.test1(..))" />
    		</aop:aspect>
    	</aop:config>
    
    </beans>
    When I try to make this work with something like this:

    Code:
    		BeanFactoryLocator bfl=SingletonBeanFactoryLocator.getInstance("classpath*:applicationContext.xml");
    		AbstractApplicationContext context=(AbstractApplicationContext)bfl.useBeanFactory("testBeanFactory").getFactory();
    		TestBean1 bean1=(TestBean1)context.getBean("testBean1");
    I get an exception

    Code:
    Exception in thread "main" org.springframework.beans.factory.access.BootstrapException: Unable to initialize group definition. Group resource name [classpath*:applicationContext.xml], factory key [testBeanFactory]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testBeanFactory' defined in URL [file:/H:/Projects/Work/SpringAOPTest/bin/applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.context.support.ClassPathXmlApplicationContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testBean1': Bean with name 'testBean1' has been injected into other beans [testAspectJAdvice] in its raw version as part of a circular reference, but has eventually been wrapped (for example as part of auto-proxy creation). This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testBeanFactory' defined in URL [file:/H:/Projects/Work/SpringAOPTest/bin/applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.context.support.ClassPathXmlApplicationContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testBean1': Bean with name 'testBean1' has been injected into other beans [testAspectJAdvice] in its raw version as part of a circular reference, but has eventually been wrapped (for example as part of auto-proxy creation). This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
    Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.context.support.ClassPathXmlApplicationContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testBean1': Bean with name 'testBean1' has been injected into other beans [testAspectJAdvice] in its raw version as part of a circular reference, but has eventually been wrapped (for example as part of auto-proxy creation). This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
    Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testBean1': Bean with name 'testBean1' has been injected into other beans [testAspectJAdvice] in its raw version as part of a circular reference, but has eventually been wrapped (for example as part of auto-proxy creation). This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:423)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:156)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:290)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:348)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:92)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:77)
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    	at java.lang.reflect.Constructor.newInstance(Constructor.java:494)
    	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:82)
    	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78)
    	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:156)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:683)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:621)
    ...
    One strange thing is that the same example starts working when in the second config. file I change the sequence of declaration of beans:

    Code:
    	<bean id="testAspectJAdvice" class="com.lycoseurope.arch.test.aop.TestAspectJAdvice">
    		<property name="testBean1" ref="testBean1"></property>
    	</bean>
    	
    	<bean id="testBean1" class="com.lycoseurope.arch.test.aop.TestBean1">
    	</bean>
    Can someone explain what's going one? I also tried using @AspectJ style annotations, and it worked perfectly without any problems but I still want to understand what is wrong with the example presented above. I will be grateful if someone helps me with this.

  • #2
    I forgot to mention that I am using Spring 2.0

    Comment


    • #3
      I suspect that the following happens:

      case 1:
      - testBean1 gets instantiated
      - testAspectJAdvice1 gets instantiated
      - the property testBean1 causes lookup of bean testBean1
      - the already instantiated testBean1 gets injected into testAspectJAdvice1
      - it is tried to advise testBean1 with testAspectJAdvice1 which fails as the "raw" (i.e. unadvised) testBean1 has already been used

      case 2:
      - testAspectJAdvice1 gets instantiated
      - the property testBean1 causes lookup and instantiation of testBean1
      - while being instantiated, testBean1 gets advised with the (yet incompletely initialized, but already instantiated aspect) testAspectJAdvice1
      - the advised version of testBean1 gets injected into testAspectJAdvice1

      Note: this is just an assumption of how I think it happens.

      However, I would suggest opening an issue in Jira as however this is resolved it should be consistent and not order-dependent.

      Regards,
      Andreas

      Comment

      Working...
      X