title: Register external @AspectJ aspects dynamically in main spring project
body: <p>I'm currently tying to integrate external @AspectJ aspects into a Spring+JSF project. That is, my aspects are implemented in seperate projects and should be loaded into the main application context at runtime. This is working fine if I declare the external aspect in my application context which is then loaded first thing in my main. </p>
  
  <pre><code>ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("app-context.xml");
  </code></pre>
  
  <p>However, I want to be able to load an unknown number of Aspects dynamically so I can package some aspects into plugins that get deployed depending on dependency settings in my maven pom. </p>
  
  <p>here's my app-context:</p>
  
  <pre><code>   &lt;?xml version="1.0" encoding="UTF-8" ?&gt;
  
  &lt;beans xmlns="http://www.springframework.org/schema/beans" 
      xmlns:aop="http://www.springframework.org/schema/aop"
      xmlns:context="http://www.springframework.org/schema/context"
      xmlns:task="http://www.springframework.org/schema/task"
      xmlns:jee="http://www.springframework.org/schema/jee"
      xmlns:jpa="http://www.springframework.org/schema/data/jpa"
      xmlns:tx="http://www.springframework.org/schema/tx" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd   
                          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
                          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                          http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd  
                          http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd  
                          http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd 
                          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
      default-autowire="byName"&gt;
  
  
      &lt;context:annotation-config /&gt;
      &lt;context:component-scan base-package="..." /&gt;
  
      &lt;import resource="app-ds-jpa.xml"/&gt;
  
      &lt;!-- a explicit --&gt;
      &lt;bean id="stopWatchProviderAspect" class="....util.StopWatchProviderAspect" /&gt;      
      &lt;!-- b dynamic --&gt;
      &lt;bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /&gt; 
  
      &lt;!-- Enable the @AspectJ support --&gt;
      &lt;aop:aspectj-autoproxy proxy-target-class="true" /&gt;
  &lt;/beans&gt;
  </code></pre>
  
  <p>StopWatchProvider is loaded via a maven dependency. Defining the bean explicitly (a) will work fine. The dynamic approach however fails with the following exception:</p>
  
  <pre><code>Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultData': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ....manager.CustomerManager ....util.DefaultData.customerManager; nested exception is java.lang.IllegalArgumentException: Can not set ....manager.CustomerManager field ....util.DefaultData.customerManager to $Proxy26
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
      at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
      at org.springframework.context.support.ClassPathXmlApplicationContext.&lt;init&gt;(ClassPathXmlApplicationContext.java:139)
      at org.springframework.context.support.ClassPathXmlApplicationContext.&lt;init&gt;(ClassPathXmlApplicationContext.java:83)
      at ....App.main(App.java:190)
  Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ....manager.CustomerManager ....util.DefaultData.customerManager; nested exception is java.lang.IllegalArgumentException: Can not set ....manager.CustomerManager field ...e.util.DefaultData.customerManager to $Proxy26
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
      at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
      ... 13 more
  Caused by: java.lang.IllegalArgumentException: Can not set ....manager.CustomerManager field ....util.DefaultData.customerManager to $Proxy26
      at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
      at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
      at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
      at java.lang.reflect.Field.set(Field.java:657)
      at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:498)
  </code></pre>
  
  <p>Don't know if that's even possible. However I found in an <a href="https://jira.springsource.org/browse/SPR-2703" rel="nofollow noreferrer">old post</a> in the comments, that the AnnotationAwareAspectJAutoProxyCreator conflicts with my Autowireing byName.</p>
  
  <p>Found somewhere else, that this kind of error suggests, I am proxying a proxy which is illegal, though I don't understand what that's supposed to mean.</p>
  
  <p>One answer to a <a href="https://stackoverflow.com/questions/6390556/aspectj-and-spring-with-aspectj-autoproxy">Related Question</a> is, that I need to do the autoproxy after all bean initialization but that didn't help (as seen in my app-context)</p>
  
  <p>I've been looking around forever for a way to autodetect my Aspects in a main application without having to staticly define them in the main app-context.xml
  I don't need to do this via the AnnotationAwareAspectJAutoProxyCreator. As long as I don't have to "register" all aspects in the one app-context.xml file I am happy.</p>
  
  <p>My alternative would be to have all plugins implement a common interface "Pluggable" with access to a PluginManager via which they could get start()ed, loading up their own application context so that I can put the bean definition in their child context .xml as a resource within their respective projects. I kind of got this to work (at least the loading of several application contexts so I can keep the bean information in the corresponging package) but I'd still prefer a more dynamic approach. </p>
  
  <p>Thanks for any pointers or maybe even answers to why I get that exception! </p>
  
  <hr>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Since no one seems to know a solution for the conflict between autowire by name and <code>AnnotationAwareAspectJAutoProxyCreator</code> we register our aspects inside their project's context now and import all project contexts into the web app that uses the aspect:</p>
  
  <p><strong>Core Project</strong>:</p>
  
  <p>Aspect:</p>
  
  <pre><code>@Aspect
  public class SomeAspect { ... }
  </code></pre>
  
  <p>core-context.xml:</p>
  
  <pre><code>&lt;bean id="someAspect" class="path.to.core.SomeAspect /&gt;         
  &lt;aop:aspectj-autoproxy proxy-target-class="true" /&gt;
  </code></pre>
  
  <p><strong>Web Project</strong>:</p>
  
  <pre><code>&lt;import resource="classpath:core-context.xml"/&gt; 
  </code></pre>
  
  <p>Then the aspect will fire in the web project as well. This suffices for us for now.</p>
  
  <p>I guess another dynamic approach would be to scan the classpath for <code>@Aspect</code> annotations inside a setup bean and register the aspects via a BeanFactory. </p>
  
  <p>Still, if anyone knows more about the conflict between <code>Autowire: by-name</code> and <code>AnnotationAwareAspectJAutoProxyCreator</code> please share it.</p>