2009-05-06 22 views
10

Sto cercando di utilizzare l'integrazione della dipendenza automatica tramite l'annotazione @Configurable di Spring w/@Resource nei campi che richiedono l'iniezione. Ciò ha comportato alcune impostazioni, come il passaggio di spring-agent.jar alla mia JVM. Per i dettagli completi see here.Perché a volte la funzione di configurazione di Spring @ funziona correttamente e talvolta no?

Funziona ... principalmente. Quando il mio Tomcat si avvia, vedo i messaggi di avvio di AspectJ, i miei oggetti User ottengono automaticamente riferimenti a FileService, ecc.

Il problema è che a volte semplicemente non accade. Sembra essere completamente casuale; a volte mi avvio e le dipendenze non vengono iniettate, a volte lo sono. In precedenza avevo avuto problemi con @Transactional sul mio utente perché creava un conflitto, credo con i proxy. Sto usando JPA, quindi il mio utente è contrassegnato con @Entity, quindi la mia ipotesi migliore ora è che questo sta creando un conflitto. Ho letto che non puoi eseguire il proxy automatico di un proxy. Per compensare il conflitto, ho seguito alcuni appunti che ho trovato online sull'esclusione di CGLIB e javassist utilizzato da Hibernate (my impl JPA).

Indizi:

  • E 'tutto o niente. Tutte le istanze @Configurable sono state iniettate o nessuna di queste.
  • Ricaricando (reinstantiating) l'entità dal DB non sembra aiutare; funziona o no.
  • Il riavvio di Tomcat da un qualsiasi numero di volte non lo risolve nemmeno. L'unica cosa che sembra tirare di nuovo i dadi è una ridistribuzione. In altre parole, se lo ridistribuisco potrebbe funzionare.

Come posso capire cosa non va? Qualcuno usa @Configurable con JPA? Perché il mio dependencyCheck = true non genera un errore quando le dipendenze non vengono effettivamente iniettate?

Entity

@Entity 
@Configurable(dependencyCheck = true) 
@NamedQueries({ @NamedQuery(name = "User.findAll", query = "SELECT user FROM User user"), 
    @NamedQuery(name = "User.findByEmail", query = "SELECT user FROM User user WHERE user.email = :email") }) 
public abstract class User extends BaseModel { 

private static final long serialVersionUID = 7881431079061750040L; 

@Id 
@GeneratedValue(strategy = GenerationType.TABLE) 
private Long id; 

@Column(unique = true, nullable = false) 
private String email; 

@Basic(optional = false) 
private String password; 

@Resource 
private transient UserEmailer userEmailer; 

@Resource 
private transient FileService fileService; 

... 

aop.xml

<!DOCTYPE aspectj PUBLIC 
    "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> 
<aspectj> 
    <weaver options="-verbose"> 
     <include within="com.myapp.domain..*" /> 
     <exclude within="*..*CGLIB*" /> 
     <exclude within="*..*javassist*" /> 
    </weaver> 
    <aspects> 
     <aspect name="org.springframework.beans.factory.aspectj.AbstractInterfaceDrivenDependencyInjectionAspect" /> 
    </aspects> 
</aspectj> 

applicationContext.xml

... 

<context:spring-configured /> 

<context:load-time-weaver /> 

<context:component-scan base-package="com.myapp" /> 

... 
+1

Anche io ho riscontrato questo tipo di problemi con @Configurable e @Transactional per a lungo penso che abbia a che fare con il caricatore di classi che carica le classi prima che il contesto di primavera sia inizializzato.Vedi questa discussione: http://forum.springsource.org/showthread.php?t=68406. La natura sporadica di – ghempton

+1

Date tutte le modifiche a Spring, ora c'è una soluzione migliore a questo problema? – Snekse

risposta

1

Quando l'iniezione doesn Funziona, per qualsiasi motivo, non c'è modo per il codice di eseguire qualsiasi controllo di dipendenza, quindi ora viene generato un errore.

Altrimenti non riesco a vedere nulla qui che indicherebbe l'errore casuale. Puoi estrarre un esempio semplificato da verificare?

+0

Ciao Jörn, grazie per il commento. Proverò un esempio semplificato quando torno a casa. Devo aggiornare questo domanda, poiché da allora sono passato dall'uso di spring-agent.jar a TomcatInstrumentableClassLoader con un ambito più piccolo, vedere la sezione 6.8.4.6.2. Tomcat del documento di riferimento Spring ent. Stranamente, questo cambiamento sembra abbassare la frequenza del problema che si verifica, ma non lo risolve del tutto. – rcampbell

+0

C'è una ragione per cui stai usando @Configurable su @Component? –

+0

Secondo la documentazione, entrambi avrebbero realizzato la stessa cosa qui. Uso @Component per l'iniezione DI su bean gestiti da Spring, mentre uso @Config per l'iniezione DI su bean non gestiti da Spring. Quindi, anche se entrambi funzionassero, io uso i diversi per suggerire lo stato di primavera di un fagiolo. – rcampbell

2

Impossibile individuare nulla di ovvio, quindi solo un suggerimento: hai provato a utilizzare la tessitura in fase di compilazione? Si spera che ciò porterebbe a risultati coerenti in fase di esecuzione, anche se può essere un po 'più complicato durante lo sviluppo.

+0

Suggerirei inoltre di utilizzare la tessitura in fase di compilazione per i deployment di produzione. Evita anche i problemi relativi a qualcuno che dimentica di impostare il parametro JDK aspect-j weaver. . . . la tessitura in fase di compilazione è ottima per i test di integrazione. –

1

Sembra che il processo di distribuzione sia sospetto. Puoi fare una distribuzione che funzioni, quindi copiarla in una directory. Quindi esegui un'altra distribuzione finché non ne ottieni una che non funziona. (In entrambi gli ordini) Quindi, infine, utilizzare uno strumento come oltre il confronto per confrontare le due strutture di directory di distribuzione e i file, e vedere se ci sono delle differenze.

Buona fortuna, niente come un problema apparentemente casuale per uccidere un po 'di produttività.

+1

Questa è davvero una buona idea che non ho mai considerato. Ci proverò stasera. A proposito, è strano che ho iniziato a usare @Configurable per INCREMENTARE la mia produttività; prima stavo facendo DI manuale in certi punti (come Factory, Repo, ecc.) e stavo inseguendo aree mancanti dove l'oggetto dominio è istanziato ma mai iniettato. In questo momento direi che @Cofig è +1 per l'eleganza, -1 per la produttività rispetto alla soluzione orig – rcampbell

+0

Sì, sono su un progetto ora, dove sto usando una serie di nuove tecnologie. Raramente migliorano la produttività fino a quando non riesci a superare la gobba. Non ho nemmeno provato ad affrontare le proprietà annotate di Spring. Troppe cose nuove e l'xml funziona sempre. –

3

Prima di tutto devo dire che probabilmente non è una buona idea avere risorse, servizi o altri bean immessi nelle classi del modello di dati come dipendenze. Ma questa è una questione di design.

Per l'utilizzo di @Configurable l'ho usato nei casi in cui gli oggetti vengono istanziati dall'esterno del contesto Spring, ad esempio tag personalizzati in applicazioni Web, filtri o servlet. Il primo modo in cui ho provato a usarli era il tempo di caricamento che si tesseva come te. Ha funzionato abbastanza bene, ma ha avuto alcuni inconvenienti come la distribuzione di hot code mentre il debug non funzionava più.

Ho anche sperimentato esattamente il problema che descrivi e così ho deciso di passare dal tempo di caricamento alla compilazione del tempo. Per questo ho installato il AJDT plugin in Eclipse e ho usato il supporto aspecjt di Spring. Questo ha risolto i miei problemi.

+0

Grazie Thomas. Ho alcune spiegazioni sul perché l'ho progettato in questo modo qui: http://stackoverflow.com/questions/694374/how-can-i-resolve-the-conflict-between-loose-coupling-dependency-injection-and-a Fondamentalmente si tratta di un design basato sul dominio che mi influenza. I miei modelli di dominio erano solo dati; rappresentavano per lo più file di tabelle.Dopo aver letto questo ottimo libro, ho deciso di spostarmi maggiormente verso OOP/dati + comportamento, le entità radice responsabili delle loro entità figlio, ecc. Un buon esempio di dove lo uso è iniettare la Factory cablata in primavera per un'entità figlio nel suo genitore. – rcampbell

+0

quale "ottimo libro" intendi? sembra interessante ... –

+0

Il libro è Domain-Driven Design di Eric Evans. L'ho saputo da una raccomandazione di Martin Fowler su Patterns of Enterprise Application Architecture che è un altro libro davvero eccezionale. – rcampbell

3

Per me sembra un'eventualità di un bug noto in primavera: http://jira.springframework.org/browse/SPR-5401.

Può essere che si stia tentando di utilizzare Configurabile in diversi contesti applicativi? In questo caso solo uno di questi sarà soggetto all'iniezione di dipendenza. Quale vincita dipende da quale contesto applicativo è l'ultimo da caricare.

Soluzione? Nessuno :-(Non ci sono piani per risolvere questo problema. Almeno quello che il ragazzo di SpringSource ha detto alla conferenza JAX in Germania nel mese di aprile

Problemi correlati