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)}
- Iniezione di una dipendenza Spring in un EntityListener JPA
- Come funziona FetchMode in Spring Data JPA
- Lettura di un elenco dal file di proprietà e caricamento con annotazione a molla @Valore
- Aggiunta di ContextLoaderListener a web.xml in Spring MVC
- Spring Transactions e hibernate.current_session_context_class
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.