Autoiniezione con la spring

Ho provato il seguente codice con Spring 3.x che non è riuscito con BeanNotFoundException e dovrebbe corrispondere alle risposte di una domanda che ho chiesto prima – Posso iniettare la stessa class usando Spring?

 @Service public class UserService implements Service{ @Autowired private Service self; } 

Poiché stavo provando questo con Java 6, ho trovato che il seguente codice funziona bene:

 @Service(value = "someService") public class UserService implements Service{ @Resource(name = "someService") private Service self; } 

ma non capisco come risolva la dipendenza ciclica.

MODIFICARE:
Ecco il messaggio di errore. L’OP lo ha menzionato in un commento su una delle risposte:

Causato da: org.springframework.beans.factory.NoSuchBeanDefinitionException: Nessun bean corrispondente di tipo [com.spring.service.Service] trovato per dipendenza: atteso almeno 1 bean che si qualifica come candidato autowire per questa dipendenza. Annotazioni sulle dipendenze: {@ org.springframework.beans.factory.annotation.Autowired (richiesto = true)}

Aggiornamento: febbraio 2016

L’autowiring automatico sarà ufficialmente supportato in Spring Framework 4.3. L’implementazione può essere vista in questo commit GitHub .


La ragione definitiva per cui non è ansible autorizzarsi autonomamente è che l’implementazione del DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor) di Spring esclude esplicitamente la possibilità. Questo è visibile nel seguente estratto di codice da questo metodo:

 for (String candidateName : candidateNames) { if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) { result.put(candidateName, getBean(candidateName)); } } 

A proposito: il nome del bean (cioè, il bean che sta cercando di autowire stesso) è beanName . Quel bean è in realtà un candidato autowire, ma la condizione if precedente restituisce false (poiché candidateName di fatto è uguale a beanName ). Quindi non puoi semplicemente autowire un bean con se stesso (almeno non a partire da Spring 3.1 M1).

Ora, per quanto riguarda il comportamento semanticamente o no, è un’altra domanda. 😉

Chiederò a Juergen e vedrò cosa ha da dire.

Saluti,

Sam (Core Spring Committer)

ps Ho aperto un problema Spring JIRA per prendere in considerazione il supporto dell’autoscupazione automatica per tipo usando @Autowired. Sentiti libero di guardare o votare per questo problema qui: https://jira.springsource.org/browse/SPR-8450

Anche questo codice funziona:

 @Service public class UserService implements Service { @Autowired private ApplicationContext applicationContext; private Service self; @PostConstruct private void init() { self = applicationContext.getBean(UserService.class); } } 

Non so perché, ma sembra che Spring possa ottenere il bean da ApplicationContext se viene creato , ma non inizializzato . @Autowired funziona prima dell’inizializzazione e non riesce a trovare lo stesso bean. Quindi, @Resource funzionare dopo @Autowired e prima di @PostConstruct .

Ma non lo so, solo speculando. Comunque, bella domanda.

A proposito, la soluzione più elegante al problema dell’autovoce è usare AspectJ Load-Time Weaving per i proxy transazionali (o qualsiasi altro proxy introdotto da AOP che si sta utilizzando).

Ad esempio, con la gestione delle transazioni basata su annotazioni, è ansible utilizzare la modalità “aspectj” come segue:

  

Si noti che la modalità predefinita è “proxy” (cioè, proxy dinamici JDK).

Saluti,

Sam

Dato il codice precedente non vedo una dipendenza ciclica. Inietti qualche istanza di servizio in UserService. L’implementazione del servizio inserito non deve necessariamente essere un altro UserService, quindi non esiste alcuna dipendenza ciclica.

Non vedo perché si inietterebbe un UserService in UserService, ma spero che questo sia un tentativo teorico o altro.

Ottenere il proxy AOP dalla domanda dell’object stesso suggerisce un approccio hacky alternativo con AopContext.currentProxy() che potrebbe essere adatto per casi speciali.

Sembra che molla crea e configura un object e poi lo posiziona nel contesto di ricerca del bean. Ma, nel caso di Java, penso che crei l’object e lo leghi al nome e alla configurazione durante la ricerca dell’object dal nome che si trova nel contesto.