Solución:
Piense en su problema por un segundo. No tienes que mantener ninguna propiedad application.properties
en campos estáticos. La “solución alternativa” sugerida por Patrick es muy sucia:
- no tienes idea de cuándo se modifica este campo estático
- no sabes qué hilo modifica su valor
- cualquier hilo en cualquier momento puede cambiar el valor de este campo estático y estás atornillado
- inicializar el campo estático privado de esa manera no tiene sentido para mí
Tenga en cuenta que cuando tenga un frijol controlado por @Service
anotación delega su creación al contenedor Spring. Spring controla este ciclo de vida del bean creando solo un bean que se comparte en toda la aplicación (por supuesto, puede cambiar este comportamiento, pero me refiero a uno predeterminado aquí). En este caso, cualquier campo estático no tiene sentido: Spring se asegura de que solo haya una instancia de UserService
. Y obtiene el error que ha descrito, porque la inicialización de campos estáticos ocurre muchos ciclos de procesador antes de que se inicien los contenedores Spring. Aquí puede encontrar más información sobre cuándo se inicializan los campos estáticos.
Sugerencia
Sería mucho mejor hacer algo como esto:
@Service
public class UserService {
private final String svnUrl;
@Autowired
public UserService(@Value("${SVN_URL}") String svnUrl) {
this.svnUrl = svnUrl;
}
}
Este enfoque es mejor por algunas razones:
- La inyección del constructor describe directamente qué valores se necesitan para inicializar el objeto.
-
final
campo significa que este valor no se cambiará después de que se inicialice en una llamada al constructor (es seguro para subprocesos)
Utilizando @ConfigurationProperties
También hay otra forma de cargar varias propiedades en una sola clase. Requiere el uso de prefijo para todos los valores que desea cargar en su clase de configuración. Considere el siguiente ejemplo:
@ConfigurationProperties(prefix = "test")
public class TestProperties {
private String svnUrl;
private int somePort;
// ... getters and setters
}
La primavera se encargará TestProperties
inicialización de la clase (creará una testProperties
bean) y puede inyectar este objeto a cualquier otro bean inicializado por el contenedor Spring. Y esto es lo ejemplar application.properties
el archivo se parece a:
test.svnUrl=https://svn.localhost.com/repo/
test.somePort=8080
Baeldung creó una gran publicación sobre este tema en su blog, recomiendo leerla para obtener más información.
Solución alternativa
Si necesita de alguna manera usar valores en un contexto estático, es mejor definir alguna clase pública con public static final
campos dentro: esos valores se instanciarán cuando el cargador de clases cargue esta clase y no se modificarán durante la vida útil de la aplicación. El único problema es que no podrá cargar estos valores desde Spring application.properties
, tendrá que mantenerlos directamente en el código (o podría implementar alguna clase que cargue valores para estas constantes desde el archivo de propiedades, pero esto suena tan detallado para el problema que está tratando de resolver).
Spring no permite inyectar valor en variables estáticas.
Una solución alternativa es crear un definidor no estático para asignar su valor a la variable estática:
@Service
public class UserService {
private static String SVN_URL;
@Value("${SVN_URL}")
public void setSvnUrl(String svnUrl) {
SVN_URL = svnUrl;
}
}
No se permite el acceso a application.properties en funciones miembro estáticas, pero aquí hay una solución alternativa,
application.properties
server.ip = 127.0.0.1
PropertiesExtractor.java
public class PropertiesExtractor {
private static Properties properties;
static {
properties = new Properties();
URL url = new PropertiesExtractor().getClass().getClassLoader().getResource("application.properties");
try{
properties.load(new FileInputStream(url.getPath()));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static String getProperty(String key){
return properties.getProperty(key);
}
}
Clase principal
public class Main {
private static PropertiesExtractor propertiesExtractor;
static{
try {
propertiesExtractor = new PropertiesExtractor();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public static getServerIP(){
System.out.println(propertiesExtractor.getProperty("server.ip")
}
}