36

私は、Spring を使用し、DAO をドメイン オブジェクトに注入して、永続層の直接的な知識を必要としないようにするというアイデアで遊んでい@Configurableます@Autowire

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-atconfigurableに従おうとしていますが、私のコードは効果がないようです。

基本的に、私は持っています:

@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);

}

@Component
public class ArtistDAOImpl implements ArtistDAO {

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

}

application-context.xml には、次のものがあります。

<?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! の spring モジュールによって実行されます。フレームワーク、他の自動配線された Bean は機能しますが、これが根本的な原因ではないと確信しています。私はSpring 3.0.5を使用しています。

他のコード (実際、Spring を使用してコントローラーに注入された Bean のメソッド内) では、次のようにしています。

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

これにより、Artist.save() で artistDao にアクセスしようとすると、NullPointerException が発生します。

私が間違っていることは何か分かりますか?

マーティン

4

10 に答える 10

10

を使用するには、ロード時のウィービング (またはその他の種類のウィービング) を有効にする必要があります@Configurable7.8.4 Spring Framework での AspectJ を使用したロード時のウィービング で説明されているように、正しく有効にしたことを確認してください。

于 2011-01-16T04:23:38.723 に答える
7

LTW を使用して Tomcat 7 でこの問題が発生し、Bean をドメイン クラスに自動接続しようとしていました。

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-configurable-containerで 3.2.x のドキュメントにいくつかの更新があり、それが明らかになったxml configuration の代わりに @EnableSpringConfigured を使用できます。

したがって、Domain オブジェクトに次の注釈があります。

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

@EnableSpringConfigured は

<context:spring-configured />

これをコンテキスト xml ファイルに追加することを忘れないでください。

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

もちろん、最初に読み込み時間のウィービング用に Tomcat をセットアップする必要がありました。

また、3.2.0 でバグ (null ポインター) に遭遇したため、Spring 3.2.1 ( https://jira.springsource.org/browse/SPR-10108 )にアップグレードする必要がありました。

すべてが順調です!

于 2013-02-14T16:10:39.060 に答える
4

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

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

これにより、Spring がいつ何を行っているかを確認できます。

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

private ArtistDAO artistDao;

@Autowired
public void setArtistDao(ArtistDAO artistDao) 
{
  this.artistDao = artistDao;
}
于 2011-04-26T14:58:41.807 に答える
4

Spring Rooはあなたがやりたいことを正確に実行するので、Spring Rooがどのようにそれを行うかを確認する必要があります。

NPE が発生する原因はたくさんありますが、ほとんどの場合、AspectJ コンパイラで適切にコンパイルされていないことと、AspectJ lib パスにSpring Aspects jarが含まれていないことが関係しています (これはクラスパスとは異なります)。

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

@Configurable がLTWで実際には機能しないことがわかりました(回答の1つがそう言っているにもかかわらず)。アドバイスはオブジェクトの構築時に行われるため、 @Configurable を機能させるにはコンパイル時のウィービングが必要です (Springs LTW ではコンストラクターのアドバイスを行うことはできません)。

于 2011-09-06T13:03:20.950 に答える
3

私は同じ問題を抱えていて、コードを @Configurable と @Autowired で動作させることができませんでした。最終的に、@Configurable および @Autowired アノテーションを処理するアスペクトを自分で作成することにしました。コードは次のとおりです。

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;
    }

}

次に、Spring コンテキストでアスペクトを定義して、SpringContext がアスペクトに注入されるようにします。

<bean class="[package_name].AutoInjectDependecyAspect" factory-method="aspectOf"/>
于 2014-06-20T13:38:08.923 に答える
1

試してみてください: @Configurable(autowire=Autowire.BY_TYPE)。Autowired のデフォルトは off :<

于 2012-01-12T15:50:02.127 に答える
1

今日解決した同様の問題がありました。重要なことは、ロード時のウィービングを有効にして、適切なアスペクトクラスがロードされていることを確認する必要があるということです。pom.xml に、aspectjweaver アーティファクトを追加する必要があります。

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

必要に応じてバージョンを変更できます。次に、DTD ルートではなく、application-context.xml の xsd ルートに移動します。

<?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>
于 2012-08-06T22:48:34.370 に答える
1

おそらく、DAO に@Repositoryアノテーションを使用すると、それが可能になります。

于 2011-01-16T01:20:51.527 に答える
0

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

于 2013-06-19T10:06:48.327 に答える