Entonces, tengo un archivo de propiedades simple con las siguientes entradas:
my.value=123
another.value=hello world
Este archivo de propiedades se está cargando mediante un PropertyPlaceHolderConfigurer
que hace referencia al archivo de propiedades anterior.
Tengo la siguiente clase, para la cual estoy tratando de cargar estas propiedades para que me gusten:
public class Config
{
@Value("${my.value}")
private String mValue;
@Value("${another.value}")
private String mAnotherValue;
// More below...
}
El problema es ese, mValue
y mAnotherValue
son SIEMPRE nulos… sin embargo, en mis Controladores, el valor se carga correctamente. ¿Lo que da?
Si instancias de Config
se están instanciando manualmente a través de new
entonces Spring no se involucra, por lo que se ignorarán las anotaciones.
Si no puede cambiar su código para hacer que Spring cree una instancia del bean (tal vez usando un prototype
-scoped bean), entonces la otra opción es usar la funcionalidad de tejido del cargador de clases en tiempo de carga de Spring (ver documentos). Este es un AOP de bajo nivel que le permite instanciar objetos como lo haría normalmente, pero Spring los pasará a través del contexto de la aplicación para conectarlos, configurarlos, inicializarlos, etc.
Sin embargo, no funciona en todas las plataformas, así que lea el enlace de documentación anterior para ver si funcionará para usted.
-
Hola skaffman, gracias por el consejo… El problema es que estoy instanciando
Config
de un JSP. No estoy seguro si puedo encontrar una forma de evitar eso. ¿Tal vez usando algún tipo de fábrica?– Polaris878
9 de noviembre de 2010 a las 16:12
-
@ Polaris878: mi sugerencia aún debería funcionar para objetos instanciados por JSP (cualquier objeto instanciado a través de la reflexión)
– Skaffman
9 de noviembre de 2010 a las 16:50
-
+1. Aprovecho para saber de Primavera en ese detalle. Hace años que no lo toco. Lugar de trabajo estúpido.
– Adeel Ansari
10 de noviembre de 2010 a las 2:25
-
+1 Dios mío… ¡esto me salva! Estaba tratando de leer archivos de propiedades y no estaba seguro de por qué @Value estaba dando nulo
– Vladtn
24 de enero de 2013 a las 13:13
-
Gracias, eso fue todo. Estaba tratando de crear una instancia de un nuevo objeto en lugar de autoconectar la clase y dejar que Spring hiciera el trabajo.
– rudyg123
7 abr 2022 a las 22:57
Tuve problemas similares pero era un novato en Spring. Estaba tratando de cargar propiedades en un @Service e intenté usar @Value para recuperar el valor de la propiedad con…
@Autowired
public @Value("#{myProperties['myValue']}") String myValue;
Pasé un día entero probando varias combinaciones de anotaciones, pero siempre devolvía nulo. Al final, la respuesta, como siempre, es obvia después del hecho.
1) asegúrese de que Spring esté escaneando su clase en busca de anotaciones al incluir la jerarquía del paquete en su servlet.xml (escaneará todo lo que esté debajo del valor base que inserte).
2) Asegúrese de que NO está ‘novando’ la clase que acaba de decirle a Spring que mire. En su lugar, usa @Autowire en la clase @Controller.
Todo en Spring es un Singleton, y lo que estaba sucediendo era que Spring cargó los valores en su Singleton, luego había “nuevo” en otra instancia de la clase que no contenía los valores recién cargados, por lo que siempre fue nulo.
En cambio, en el uso de @Controller …
@Autowired
private MyService service;
Depuración… Una cosa que hice para encontrar esto fue extender mi servicio de la siguiente manera…
@Service
public class MyService implements InitializingBean
A continuación, introduzca declaraciones de depuración en…
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
LOGGER.debug("property myValue:" + myValue);
}
Aquí pude ver que el valor se establecía en la inicialización, y más tarde, cuando lo imprimí en un método, era nulo, por lo que esta fue una buena pista para mí de que no era la misma instancia.
Otra pista de este error fue que Tomcat se quejó de que los tiempos de espera intentaban leer desde el zócalo sin poder analizar el encabezado HTTP… Esto se debió a que Spring había creado una instancia del servicio y yo también, por lo que la mía estaba haciendo el trabajo real. y Spring se estaba agotando en su instancia.
-
¿Qué es myProperties aquí? podría explicar por favor.
– SIMA
3 de julio de 2018 a las 15:44
-
Fue el número 2 en mi caso. Cambiar de declaración como
new
a@Autowired
resolvió mi problema– Jack El Cuchillo
12 de marzo de 2019 a las 17:31
escocés
Mira mi respuesta aquí.
Me encontré con los mismos síntomas (@Value
-campos anotados siendo null
) pero con un problema subyacente diferente:
import com.google.api.client.util.Value;
Asegúrese de que está importando el @Value
clase de anotación! Especialmente con la conveniencia de los IDE hoy en día, este es un error MUY fácil de cometer (estoy usando IntelliJ, y si importas automáticamente demasiado rápido sin leer QUÉ estás importando automáticamente, podrías perder algunas horas como lo hice yo).
La importación correcta es:
org.springframework.beans.factory.annotation.Value
-
¡Gran hallazgo! En mi caso, estaba sombreando las dependencias regulares de Spring Boot con el complemento “org.springframework.boot”.
– diman82
3 de junio de 2020 a las 13:32
-
¿Cuál es la notación correcta? esto debe proporcionarse en una respuesta
– notacorn
2 de marzo de 2022 a las 0:06
-
Agregué la importación correcta a la respuesta.
– scottysseus
2 de marzo de 2022 a las 15:25
Como está trabajando con @Controller
parece que estás instanciando Config
tú mismo. Deja que Spring lo ejemplifique.
Keiv
También puedes hacer tus propiedades private
asegúrese de que su clase sea un Spring bean usando @Service
o @Component
anotaciones para que siempre se cree una instancia y, finalmente, agregar métodos setter anotados con @Value
. Esto garantiza que a sus propiedades se les asignen los valores especificados en sus archivos de configuración application.properties o yml.
@Service
public class Config {
private static String myProperty;
private static String myOtherProperty;
@Value("${my.value}")
public void setMyProperty(String myValue) {
this.myProperty = myValue;}
@Value("${other.value}")
public void setMyOtherProperty(String otherValue) {
this.myOtherProperty = otherValue;}
//rest of your code...
}
cábala
Agregar <context:spring-configured />
a su archivo de contexto de la aplicación.
Luego agrega el @Configurable
anotación a Config
clase.
JoSSte
En mi caso, en mi prueba de unidad, executeScenarioRequest siempre es nulo
@RunWith(SpringRunner.class)
@ExtendWith(MockitoExtension.class)
class ScenarioServiceTestOld {
@Value("classpath:scenario/SampleScenario.json")
Resource executeScenarioRequest;
Cambiar @ExtendWith(MockitoExtension.class)
a @ExtendWith(SpringExtension.class)
¿La clase Config se define como un bean de primavera?
– Raghuram
9 de noviembre de 2010 a las 4:28
¿No? ¿Cómo haría eso con las anotaciones?
– Polaris878
9 de noviembre de 2010 a las 4:39
Intenté usar “@Component” y “@Controller” en la clase y ninguno funcionó
– Polaris878
9 de noviembre de 2010 a las 4:57
¿Cómo está funcionando en
Controller
¿entonces? ¿Qué es diferente en su controlador?– Adeel Ansari
9 de noviembre de 2010 a las 4:58
Eso es lo que me deja tan desconcertado… la clase Config está en el mismo paquete y todo… la única diferencia es que con mi controlador que funciona, en realidad tengo un mapeo de solicitud.
– Polaris878
9 de noviembre de 2010 a las 5:00