Auto inyección con Spring

BeanNotFoundException el siguiente código con Spring 3.x que falló con BeanNotFoundException y debería hacerlo según las respuestas a una pregunta que hice antes: ¿Puedo inyectar la misma clase usando Spring?

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

Como estaba intentando esto con Java 6, encontré que el siguiente código funciona bien:

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

pero no entiendo cómo se resuelve la dependencia cíclica.

EDITAR:
Aquí está el mensaje de error. El OP lo mencionó en un comentario sobre una de las respuestas:

Causado por: org.springframework.beans.factory.NoSuchBeanDefinitionException: no se ha encontrado ningún bean de tipo [com.spring.service.Service] encontrado para la dependencia: se espera al menos 1 bean que califique como candidato de autowire para esta dependencia. Anotaciones de dependencia: {@ org.springframework.beans.factory.annotation.Autowired (required = true)}

Actualización: febrero de 2016

Self autowiring será oficialmente compatible con Spring Framework 4.3. La implementación se puede ver en este commit de GitHub .


La razón definitiva por la que no puede auto-conectarse es que la implementación del método DefaultListableBeanFactory.findAutowireCandidates(String, Class, DependencyDescriptor) de Spring excluye explícitamente la posibilidad. Esto es visible en el siguiente fragmento de código de este método:

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

FYI: el nombre del frijol (es decir, el frijol que intenta autoboostse) es beanName . That bean es, de hecho, un candidato de autowire, pero la condición if anterior devuelve false (ya que candidateName de hecho es igual a beanName ). Por lo tanto, simplemente no puede autoboost un bean consigo mismo (al menos no a partir del Spring 3.1 M1).

Ahora, en cuanto a si esto es intencional o no, semánticamente hablando, esa es otra pregunta. 😉

Preguntaré a Juergen y veré lo que tiene que decir.

Saludos,

Sam (Core Spring Committer)

ps He abierto un problema Spring JIRA para considerar la posibilidad de autoautenticar por tipo usando @Autowired. Siéntase libre de mirar o votar este problema aquí: https://jira.springsource.org/browse/SPR-8450

Este código también funciona:

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

No sé por qué, pero parece que Spring puede obtener el bean de ApplicationContext si se crea , pero no se inicializa . @Autowired funciona antes de la inicialización y no puede encontrar el mismo bean. Entonces, @Resource puede funcionar luego de @Autowired y antes de @PostConstruct .

Pero no sé, solo estoy especulando. De todos modos, buena pregunta.

Por cierto, la solución más elegante al problema de auto invocación es usar AspectJ Load-Time Weaving para sus proxies transaccionales (o cualquier proxy introducido por AOP que esté usando).

Por ejemplo, con la gestión de transacciones basada en anotaciones, puede usar el modo “aspectj” de la siguiente manera:

  

Tenga en cuenta que el modo predeterminado es “proxy” (es decir, proxies dynamics JDK).

Saludos,

Sam

Dado el código anterior, no veo una dependencia cíclica. Usted inyecta una instancia de Servicio en UserService. La implementación del Servicio inyectado no necesariamente necesita ser otro UserService, por lo que no existe una dependencia cíclica.

No veo por qué se inyectaría un UserService en UserService, pero espero que sea una prueba teórica o tal.

Obtener el proxy AOP del objeto en sí pregunta sugiere un enfoque alternativo hacky con AopContext.currentProxy() que puede ser adecuado para casos especiales.

Parece que Spring crea y configura un objeto y luego lo coloca en el contexto de búsqueda de beans. Pero, en el caso de Java, creo que crea el objeto y lo vincula con el nombre y durante la configuración cuando el objeto se busca por el nombre que se encuentra en el contexto.