2011-01-16 5 views
29

私はSpringの@Configurable@Autowireを使用してドメインオブジェクトにDAOを注入し、パーシスタンスレイヤーを直接知る必要はないと考えています。@Configurableを使用した春のオートワイヤリング

私はに従おうとしていますが、私のコードは効果がないようです。

基本的に、私が持っている:

@Configurable 
public class Artist { 

    @Autowired 
    private ArtistDAO artistDao; 

    public void setArtistDao(ArtistDAO artistDao) { 
     this.artistDao = artistDao; 
    } 

    public void save() { 
     artistDao.save(this); 
    } 

} 

そして:

public interface ArtistDAO { 

    public void save(Artist artist); 

} 

およびアプリケーションのcontext.xmlで

@Component 
public class ArtistDAOImpl implements ArtistDAO { 

    @Override 
    public void save(Artist artist) { 
     System.out.println("saving"); 
    } 

} 

、私が持っている:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springsource.org/dtd/spring-beans-2.0.dtd"> 
<beans> 

    <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /> 
    <bean class="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect" factory-method="aspectOf"/> 

</beans> 

クラスパスのスキャンと初期化は、Play!のスプリングモジュールによって実行されます。フレームワークは、他のautowired豆が動作しますが、私はこれが根本的な原因ではないと確信しています。私はSpring 3.0.5を使用しています。他のコードで

(実際には春を使用して、私のコントローラに注入していますBean内のメソッド内で)、私はこれをやっている:

Artist artist = new Artist(); 
artist.save(); 

これは私のアーティストでartistDaoにアクセスしようとするとNullPointerExceptionを与えます。セーブ()。

私が間違っていることを知っていますか?マーティン

+0

関連;)http://techblog.bozho.net/?p=180は – Bozho

+0

あなたは 'Configurable' @で[値]注釈@'使用することはできますが、クラスのアーティストをマーク? – NightWolf

答えて

1

おそらくそれを行いますDAOのため@Repositoryアノテーションを使用。

+0

私は同意します。彼は代わりに@Repositoryを使うべきです – chris

+2

これは '@ Configurable 'にどのように関連付けることができますか? – axtavt

+5

なぜそれが違いをもたらすのか説明できますか? – Paul

7

@Configurableを使用するには、ロードタイム織り(または他の種類の製織)を有効にする必要があります。 7.8.4 Load-time weaving with AspectJ in the Spring Frameworkで説明されているように、正しく有効にしてください。

+1

これは間違っています。 @ConfigurableをサポートするためにLTWは必要ありません。 Spring Rooは彼が望むことを行い、LTWは使用しません。おそらく彼の問題は、AspectJコンパイラとSpring Aspects jarでコードをコンパイルしていないということです。 –

+4

@AdamGent彼はLTW(または他の種類の製織)と言った。 。 。あなたは、Configurableアノテーションのためのロード時間織りかコンパイル時間織りのいずれかが必要です。 –

+0

@JasperBluesあなたはLTWがうまくいくはずです。私は自分の環境で動作することは決してできませんでした。* AspectJ in Action *で、LTWではアドバイスの構築が不可能であったことを読みました。 –

4

まず、Springデバッグログを有効にします。私はそれを行うLog4jを使用します。 (私はRollingFileAppenderを使用できるようにLog4jのXML構成で)私はそうのようなロガーを作成しました:

<log4j:configuration> 
    <appender name="roll" class="org.apache.log4j.rolling.RollingFileAppender"> 
    blah blah configuration blah blah 
    </appender> 
    <logger name="org.springframework"> 
    <level value="debug" /> 
    <appender-ref ref="roll" /> 
    </logger> 
</log4j:configuration> 

これは春がやってたときにされたかを確認することができます。

第2に、あなたはArtistDAOを自作していますが、ArtistDAOという名前のBeanがどこにあるのかわかりません。あなたのDAOコンポーネントのbeanは、デフォルトで "artistDaoImpl"という名前になります。 @Component("artistDao")@Componentを変更し、代わりにセッターに@Autowiredを適用してみてください。

private ArtistDAO artistDao; 

@Autowired 
public void setArtistDao(ArtistDAO artistDao) 
{ 
    this.artistDao = artistDao; 
} 
3

あなたはそれはあなたがやりたいまさにないのでSpring Rooはそれをしない方法になります。

ありNPEは、あなたの持っ引き起こす可能性があり、物事の多くはあるが、それは(AspectJのコンパイラで正しくコンパイルしないと、あなたのAspectJのlibパスに春の側面ジャーを持っていないと、これを行うために持っているほとんどの時間あなたのクラスパスとは異なります)。

まず、MavenとAspectJコンパイラプラグインで動作するようにしてください。それは正しいセットアップでPOMファイルを生成するので、なぜ私はSpring Rooをお勧めします。

@ConfigurableはLTWと実際には動作しません(答えの1つにもかかわらず)。 @Configurableは、オブジェクトの作成時にアドバイスが発生しているため、@Configurableをコンパイルする必要があります(コンストラクターのアドバイスは、Spring LTWでは実行できません)。

+0

積載時にどのような問題がありましたか?私はそれをかなりうまく使用しました。統合テストにはLTWを、デプロイにはコンパイル時の織りを使用します。 。このように、私のテストカバレッジレポートはうまく出てきますが、私の展開は堅牢です。 –

+0

'@ Configurable'は、通常のJavaコンストラクタを使用してオブジェクトをインスタンス化できるためです。アドバイスはObjectsコンストラクタに適用されます。 **コンパイル時にコンストラクタのアドバイスを適用することしかできないと思っていました**しかし、LTWでも行うことができます。だからあなたは正しい。あなたがすることができないこと(そして、これが私が混乱した理由です)は、AspectJ ITDs with LTWを作成することです。 –

+0

ああ、そうです。 。それを知らなかった。 –

1

try:@Configurable(autowire = Autowire.BY_TYPE)。オートワイヤードのデフォルト値はoff:<

1

私は今日解決した同様の問題がありました。重要なことは、ロード時の織りを有効にし、適切なaspectjクラスがロードされていることを確認する必要があることです。あなたのpom.xmlでは、aspectjweaver artifactを追加する必要があります。

... 
<dependency> 
    <groupId>org.aspectj</groupId> 
    <artifactId>aspectjweaver</artifactId> 
    <version>1.6.12</version> 
</dependency> 
.... 

あなたがする必要がある場合は、バージョンを変更することができます。その後、私は、DTDのルートの代わりに使用するアプリケーションのcontext.xmlでXSDルートを行くだろう:私は自分のドメインクラスに豆をautowireしようとしているLTWを使用してTomcatの7でこの問題を抱えていた

<?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:context="http://www.springframework.org/schema/context" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 

    <!--Scans the classpath for annotated components @Component, @Repository, @Service, and @Controller --> 
    <context:component-scan base-package="your.base.package"/> 
    <!--Activates @Required, @Autowired, @PostConstruct, @PreDestroy and @Resource --> 
    <context:annotation-config/> 
    <!--This switches on the load-time weaving for @Configurable annotated classes --> 
    <context:load-time-weaver/> 

</beans> 
6

xxx構成の代わりに@EnableSpringConfiguredを使用できることが判明したhttp://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-configurable-containerの3.2.xに関するドキュメントの一部が更新されました。

だから私は私のドメインオブジェクトで次の注釈を持っている:

@Configurable(preConstruction=true,dependencyCheck=true,autowire=Autowire.BY_TYPE) 
@EnableSpringConfigured 

@EnableSpringConfiguredは

<context:spring-configured /> 

ためsubstitueであり、あなたのコンテキストxmlファイルにこれを追加することを忘れないでください:

<context:load-time-weaver weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver" aspectj-weaving="on"/> 

もちろん、最初にロード時間を設定するためにTomcatをセットアップする必要がありました。

また、私は(NULLポインタ)3.2.0のバグに遭遇したので、私は春の3.2.1(https://jira.springsource.org/browse/SPR-10108)にアップグレードするために必要な

すべてが今もです!

0

また、AspectJのバージョンが最新であることを確認してください。私はこの作業をしようと数時間を費やしましたが、原因は古いバージョンのAspectjweaver.jarでした。私は1.7.2に更新され、すべてが魅力的に機能しました。

3

私は同じ問題を抱えていて、@Configurableと@Autowiredで動作するコードを手に入れられませんでした。ついに@Configurableアノテーションと@Autowiredアノテーションを扱うという側面を自分自身で書くことに決めました。ここでは、コードです:springcontextは@ConfigurableとLTWとバグがあり様相

<bean class="[package_name].AutoInjectDependecyAspect" factory-method="aspectOf"/> 
0

に注入されるように、あなたの春のコンテキストで

import java.lang.annotation.Annotation; 
import java.lang.reflect.Field; 

import org.apache.log4j.Logger; 
import org.aspectj.lang.JoinPoint; 
import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.Before; 
import org.aspectj.lang.annotation.Pointcut; 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.ApplicationContextAware; 

@SuppressWarnings("rawtypes") 
@Aspect 
public class AutoInjectDependecyAspect implements ApplicationContextAware { 
    private static final Logger LOGGER = Logger.getLogger(AutoInjectDependecyAspect.class); 

    private ApplicationContext applicationContext = null; 

    @Pointcut("execution( (@org.springframework.beans.factory.annotation.Configurable *).new())") 
    public void constructor() { 
    } 

    @Before("constructor()") 
    public void injectAutoWiredFields(JoinPoint aPoint) { 
     Class theClass = aPoint.getTarget().getClass(); 
     try{ 
      Field[] theFields = theClass.getDeclaredFields(); 
      for (Field thefield : theFields) { 
       for (Annotation theAnnotation : thefield.getAnnotations()) { 
        if (theAnnotation instanceof Autowired) { 
         // found a field annotated with 'AutoWired' 
         if (!thefield.isAccessible()) { 
          thefield.setAccessible(true); 
         } 

         Object theBean = applicationContext.getBean(thefield.getType()); 
         if (theBean != null) { 
          thefield.set(aPoint.getTarget(), theBean); 
         } 
        } 
       } 
      } 
     } catch (Exception e) { 
      LOGGER.error("An error occured while trying to inject bean on mapper '" + aPoint.getTarget().getClass() + "'", e); 
     } 

    } 

    @Override 
    public void setApplicationContext(ApplicationContext aApplicationContext) throws BeansException { 
     applicationContext = aApplicationContext; 
    } 

} 

次は、アスペクトを定義します。どのような方法でもクラスをパラメータとして使用すると、自動配線が機能しなくなります。 https://jira.spring.io/plugins/servlet/mobile#issue/SPR-8502

関連する問題