Autowiring di spring con @Configurable

Sto giocando con l’idea di utilizzare Spring @Configurable e @Autowire per iniettare DAO in oggetti di dominio in modo che non abbiano bisogno della conoscenza diretta del livello di persistenza.

Sto cercando di seguire http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-atconfigurable , ma il mio codice sembra non avere alcun effetto.

Fondamentalmente, ho:

 @Configurable public class Artist { @Autowired private ArtistDAO artistDao; public void setArtistDao(ArtistDAO artistDao) { this.artistDao = artistDao; } public void save() { artistDao.save(this); } } 

E:

 public interface ArtistDAO { public void save(Artist artist); } 

e

     @Component public class ArtistDAOImpl implements ArtistDAO { @Override public void save(Artist artist) { System.out.println("saving"); } } 

    In application-context.xml, ho:

           

    La scansione del percorso di class e l’inizializzazione vengono eseguite dal modulo molla per Play! framework, sebbene altri bean autowired funzionino, quindi sono abbastanza sicuro che questa non sia la causa principale. Sto usando Spring 3.0.5.

    In un altro codice (all’interno di un metodo in bean che è stato iniettato nel mio controller usando Spring, infatti), sto facendo questo:

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

    Questo mi dà una NullPointerException che tenta di accedere all’artistaDao Artist.save ().

    Qualche idea su cosa sto facendo male?

    balestruccio

    È necessario abilitare la tessitura a tempo di caricamento (o altri tipi di tessitura) per utilizzare @Configurable . Assicurati di averlo abilitato correttamente, come descritto nella sezione 7.8.4 Tessitura a tempo di caricamento con AspectJ in Spring Framework .

    Stavo avendo questo problema con Tomcat 7 usando LTW che cercava di autowire i bean nelle mie classi di dominio.

    Sono stati apportati alcuni aggiornamenti al documento per 3.2.x all’indirizzo http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-configurable-container che ha rivelato che si può usare @EnableSpringConfigured invece della configurazione xml.

    Quindi ho la seguente annotazione sul mio object Dominio:

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

    @EnableSpringConfigured è un sostituto di

      

    e non dimenticare di aggiungere questo al file xml del tuo contesto:

      

    Ovviamente avevo bisogno di configurare Tomcat per caricare prima il tempo di caricamento.

    Inoltre, mi sono imbattuto in un bug in 3.2.0 (puntatore nullo), quindi ho dovuto eseguire l’aggiornamento a Spring 3.2.1 ( https://jira.springsource.org/browse/SPR-10108 )

    Tutto va bene ora!

    Innanzitutto, abilita la registrazione debug di Spring. Io uso Log4j per farlo. Ho creato un logger come tale (con la configurazione xml Log4j in modo da poter usare RollingFileAppender):

       blah blah configuration blah blah       

    Questo ti permetterà di vedere cosa sta facendo la spring e quando.

    Secondo, hai ArtistDAO autowired ma non vedo dove hai un bean chiamato ArtistDAO. Il tuo bean componente DAO sarà denominato “artistDaoImpl” per impostazione predefinita. Prova a cambiare @Component con @Component("artistDao") e applica invece @Autowired al setter:

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

    Dovresti solo vedere come funziona Spring Roo poiché fa esattamente ciò che vuoi fare.

    Ci sono molte cose che possono causare l’NPE, ma la maggior parte delle volte si tratta di non compilare correttamente con il compilatore AspectJ e di non avere il jar Spring Aspects nel tuo pathway AspectJ lib (questo è diverso dal tuo classpath).

    Per prima cosa prova a farlo funzionare con Maven e il plugin del compilatore AspectJ. Ecco perché raccomando Spring Roo perché genererà un file POM con la corretta impostazione.

    Ho trovato che @Configurable non funziona veramente con LTW (nonostante una delle risposte lo dica). Hai bisogno di tessere il tempo di compilazione per configurare @Configurable perché il consiglio sta accadendo in fase di costruzione degli oggetti (il consiglio del costruttore non può essere fatto con Springs LTW).

    Ho avuto lo stesso problema e non sono mai riuscito a far funzionare il codice con @Configurable e @Autowired. Alla fine ho deciso di scrivere personalmente un aspetto che gestisse le annotazioni @Configurable e @Autowired. Ecco il codice:

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

    Avanti nel tuo contesto primaverile definire l’aspetto in modo che il contesto primaverile venga iniettato nell’aspetto

      

    Forse usando l’annotazione @Repository per DAO lo farà.

    prova: @Configurable (autowire = Autowire.BY_TYPE). Le impostazioni predefinite automatiche sono distriggerste: <

    Ho avuto un problema simile che ho risolto oggi. L’importante è che sia necessario abilitare la tessitura a tempo di caricamento e assicurarsi che vengano caricate le classi aspectj appropriate. Nel tuo pom.xml devi aggiungere l’ artefatto aspectjweaver :

     ...  org.aspectj aspectjweaver 1.6.12  .... 

    È ansible modificare la versione se necessario. Quindi, passerei il percorso xsd in te application-context.xml invece della rotta DTD:

              

    Inoltre, si prega di verificare che la versione di AspectJ sia aggiornata. Ho perso un paio d’ore cercando di farlo funzionare, e la causa era una vecchia versione di Aspectjweaver.jar. Ho aggiornato alla 1.7.2 e tutto ha funzionato come un fascino.

    C’è un bug con @Configurable e LTW. Se si utilizza la class come parametro in qualsiasi metodo, il cablaggio automatico smette di funzionare. https://jira.spring.io/plugins/servlet/mobile#issue/SPR-8502