2009-05-06 16 views
10

Estoy tratando de usar la inyección de dependencia automática a través de la anotación @Configurable de Spring w/@Resource en los campos que necesitan inyección. Esto implicó alguna configuración, como pasar spring-agent.jar a mi JVM. Para los detalles completos see here.¿Por qué a veces funciona el @Configurable de Spring ya veces no?

Funciona ... principalmente. Cuando mi Tomcat está arrancando, veo los mensajes de inicio de AspectJ, mis objetos de usuario obtienen referencias de FileService automáticamente, etc.

El problema es que a veces simplemente no sucede. Parece ser completamente al azar; a veces reinicio y las dependencias no se inyectan, a veces lo hacen. Anteriormente tuve problemas con @Transactional en mi usuario porque creó un conflicto, creo que con proxies. Estoy usando JPA, por lo que mi usuario está marcado con @Entity, por lo que mi mejor intento ahora es que esto está creando un conflicto. He leído que no puedes autorizar automáticamente un proxy. Para compensar el conflicto, seguí algunas notas que encontré en línea sobre la exclusión de CGLIB y javassist que utiliza Hibernate (mi JPA impl).

pistas:

  • Es todo o nada. Todas mis instancias @Configurable han sido inyectadas o ninguna de ellas.
  • Recargar (volver a instalar) la entidad de la base de datos no parece ayudar; está funcionando o no.
  • Reiniciar Tomcat cualquier cantidad de tiempo tampoco lo arreglará. Lo único que parece tirar los dados nuevamente es una redistribución. En otras palabras, si vuelvo a desplegarlo, puede funcionar.

¿Cómo puedo averiguar qué está pasando mal? ¿Alguien está usando @Configurable con JPA? ¿Por qué no está mi dependencyCheck = true lanzando un error cuando las dependencias no se han inyectado realmente?

Entidad

@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

Yo también he tenido este tipo de problemas con @Configurable y @Transactional para un largo tiempo. Creo que tiene que ver con el cargador de clases que carga las clases antes de que se inicialice el contexto de primavera. Consulte este hilo: http://forum.springsource.org/showthread.php?t=68406. La naturaleza esporádica de este error es extremadamente molesto. – ghempton

+1

Teniendo en cuenta todos los cambios a Spring, ¿hay ahora una mejor solución para este problema? – Snekse

Respuesta

1

Cuando la inyección doesn No funciona, por la razón que sea, no hay forma de que el código realice ninguna comprobación de dependencia, por lo que ahora se produce un error.

De lo contrario, no puedo ver nada aquí que indique la falla aleatoria. ¿Puedes extraer un ejemplo simplificado para verificar?

+0

Hola Jörn, gracias por el comentario. Voy a intentar un ejemplo simplificado cuando llegue a casa. Necesito actualizar esto. pregunta, porque desde entonces he cambiado el uso de spring-agent.jar a un TomcatInstrumentableClassLoader de menor alcance, consulte la sección 6.8.4.6.2. Tomcat of the Spring docum reference ent. Curiosamente, este cambio parece disminuir la frecuencia del problema, pero no lo soluciona por completo. – rcampbell

+0

¿Hay algún motivo por el que esté utilizando @Configurable en @Component? –

+0

Según la documentación, ambos lograrían lo mismo aquí. Utilizo @Component para inyección DI en beans administrados por Spring, mientras uso @Config para inyección DI en beans no manejados por Spring. Así que aunque ambos funcionarían, uso los diferentes para dar pistas sobre el estado de primavera de un frijol. – rcampbell

2

No se puede detectar nada obvio, solo una sugerencia: ¿ha intentado usar el tejido en tiempo de compilación? Es de esperar que eso conduzca a resultados consistentes en el tiempo de ejecución, aunque puede ser un poco más complicado durante el desarrollo.

+0

También sugiero usar el tejido en tiempo de compilación para implementaciones de producción. También evita problemas relacionados con el olvido de alguien al establecer el parámetro JDK de weaver aspect-j. . . . El tejido en tiempo de compilación es ideal para pruebas de integración. –

1

Parece que su proceso de implementación es sospechoso. ¿Puedes hacer una implementación que funcione y luego copiarla en un directorio? Luego haga otra implementación hasta que obtenga una que no funcione. (En cualquier orden) Finalmente, utilice una herramienta como incomparable para comparar las dos estructuras y archivos de directorio de implementación, y vea si hay alguna diferencia.

Buena suerte, nada como un problema aparentemente aleatorio para matar algo de productividad.

+1

Esa es una muy buena idea que nunca consideré. Lo probaré esta noche. Por cierto, es divertido que comencé a usar @Configurable para AUMENTAR mi productividad; antes estaba haciendo DI manual en ciertos puntos (como Factory, Repo, etc.) y estaba persiguiendo áreas perdidas donde el objeto de dominio se instancia pero nunca se inyecta. Ahora mismo diría que @Cofig tiene +1 por elegancia, -1 por productividad en comparación con la solución original – rcampbell

+0

Sí, estoy en un proyecto ahora, donde estoy usando un conjunto de nuevas tecnologías. Raramente mejoran la productividad hasta que llegas a la cima. Ni siquiera intenté enfrentar las propiedades anotadas de la primavera. Demasiadas cosas nuevas, y el xml funciona siempre. –

3

Primero, tengo que decir que probablemente no sea una buena idea tener recursos, servicios u otros beans inyectados en clases de modelo de datos como dependencias. Pero esa es una cuestión de diseño.

Para el uso de @Configurable lo usé en los casos en que se crean instancias de objetos fuera del contexto Spring, como etiquetas personalizadas en aplicaciones web, filtros o servlets. La primera forma en que traté de usarlos fue por el tiempo de carga tejiendo como lo haces. Eso funcionó bastante bien, pero tenía algunos inconvenientes, como la implementación de código caliente, mientras que la depuración ya no funcionaba.

También experimenté exactamente el problema que describes y decidí pasar de tiempo de carga a tiempo de compilación. Por lo tanto, instalé el AJDT plugin en Eclipse y utilicé el soporte específico de Spring. Eso resolvió mis problemas.

+0

Gracias Thomas. Tengo una explicación de por qué lo diseñé de esta manera aquí: http://stackoverflow.com/questions/694374/how-can-i-resolve-the-conflict-between-loose-coupling-dependency-injection-and-a Básicamente se trata de un diseño de dominio que me influye. Mis modelos de dominio solían ser solo datos; en su mayoría representaban filas de la mesa.Después de leer este muy buen libro, decidí avanzar más hacia el comportamiento de OOP/datos +, las entidades raíz son responsables de sus entidades secundarias, etc. Un buen ejemplo de dónde uso esto es inyectar la Factory con cable de Spring para una entidad hija en su padre. – rcampbell

+0

¿A qué "libro muy bueno" quieres decir? suena interesante ... –

+0

El libro está basado en el dominio del diseño de Eric Evans. Me enteré por recomendación de Martin Fowler en Patterns of Enterprise Application Architecture, que es otro gran libro. – rcampbell

3

Para mí, suena como una ocurrencia de un error bien conocido en Spring: http://jira.springframework.org/browse/SPR-5401.

¿Puede ser que esté intentando usar Configurable en varios contextos de aplicación? En este caso, solo uno de ellos estará sujeto a inyección de dependencia. El que gane depende del contexto de la aplicación que sea el último en ser cargado.

¿Solución? Ninguno :-(No hay planes para solucionar este problema. Eso es al menos lo que el tipo de SpringSource dijo en la conferencia JAX en Alemania en abril.

Cuestiones relacionadas