1

私は現在、外部の@AspectJアスペクトをSpring+JSFプロジェクトに統合しようとしています。つまり、私の側面は別々のプロジェクトに実装されており、実行時にメインアプリケーションコンテキストにロードする必要があります。これは、アプリケーションコンテキストで外部アスペクトを宣言し、メインで最初にロードされる場合、正常に機能しています。

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("app-context.xml");

ただし、不明な数のアスペクトを動的にロードできるようにしたいので、MavenPomの依存関係設定に応じてデプロイされるプラグインにいくつかのアスペクトをパッケージ化できます。

これが私のアプリコンテキストです:

   <?xml version="1.0" encoding="UTF-8" ?>

<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">


    <context:annotation-config />
    <context:component-scan base-package="..." />

    <import resource="app-ds-jpa.xml"/>

    <!-- a explicit -->
    <bean id="stopWatchProviderAspect" class="....util.StopWatchProviderAspect" />      
    <!-- b dynamic -->
    <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /> 

    <!-- Enable the @AspectJ support -->
    <aop:aspectj-autoproxy proxy-target-class="true" />
</beans>

StopWatchProviderは、Mavenの依存関係を介してロードされます。Beanを明示的に定義すると(a)正常に機能します。ただし、動的アプローチは、次の例外を除いて失敗します。

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.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(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)

それが可能かどうかわからない。ただし、コメントの古い投稿で、AnnotationAwareAspectJAutoProxyCreatorがAutowireingbyNameと競合していることがわかりました。

この種のエラーが示唆している他の場所で、私は違法なプロキシをプロキシしていますが、それが何を意味するのかはわかりません。

関連する質問への1つの答えは、すべてのBeanの初期化後に自動プロキシを実行する必要があるが、それは役に立たなかったということです(私のアプリコンテキストで見られるように)

メインのapp-context.xmlでアスペクトを静的に定義することなく、メインのアプリケーションでアスペクトを自動検出する方法をずっと探していました。AnnotationAwareAspectJAutoProxyCreatorを介してこれを行う必要はありません。1つのapp-context.xmlファイルにすべての側面を「登録」する必要がない限り、私は満足しています。

私の代替案は、すべてのプラグインに、開始()されることができるPluginManagerへのアクセス権を持つ共通インターフェース「Pluggable」を実装させ、独自のアプリケーションコンテキストをロードして、Bean定義を子コンテキスト.xmlに配置できるようにすることです。それぞれのプロジェクト内のリソースとして。私はこれを機能させました(少なくとも、対応するパッケージにBean情報を保持できるように、いくつかのアプリケーションコンテキストをロードします)が、それでもより動的なアプローチを好みます。

ポインタをありがとう、あるいは私がその例外を受け取る理由への答えさえもあります!


編集:

名前によるautowire間の競合の解決策を誰も知らないようで、AnnotationAwareAspectJAutoProxyCreator今すぐプロジェクトのコンテキスト内にアスペクトを登録し、アスペクトを使用するWebアプリにすべてのプロジェクトコンテキストをインポートします。

コアプロジェクト

側面:

@Aspect
public class SomeAspect { ... }

core-context.xml:

<bean id="someAspect" class="path.to.core.SomeAspect />         
<aop:aspectj-autoproxy proxy-target-class="true" />

Webプロジェクト

<import resource="classpath:core-context.xml"/> 

次に、アスペクトはWebプロジェクトでも起動します。今のところ、これで十分です。

@Aspect別の動的なアプローチは、セットアップBean内のアノテーションのクラスパスをスキャンし、BeanFactoryを介してアスペクトを登録することだと思います。

それでも、誰かが間の対立についてもっと知っているなら、それを共有してくださいAutowire: by-nameAnnotationAwareAspectJAutoProxyCreator

4

0 に答える 0