Escenas:
- Paquete de herramientas para facilitar el procesamiento comercial
- Los frijoles administrados por resorte deben llamarse en la clase de herramienta
- La llamada de prueba informa un problema de excepción de puntero nulo
Código de herramienta preliminar:
@Component public class ScriptExecuteContent { @Autowired private static SignRepository signRepository; public static String checkSign(String certNo, String acctNo, String instCode) { Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode); if (null != sign && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code()) && DateUtil.getCurrentDate().before(sign.getExpireTime())) { return "1"; } else { return "0"; } } }
El código es deslumbrante y no tiene nada de malo, pero se ejecutará con una excepción nula, porque el signRepository inyectado aquí es nulo. Esto se debe a que el método estático pertenece a la clase y el método ordinario pertenece al objeto. Spring La inyección se instancia en el contenedor. Las variables y estática existe en preferencia a los objetos, por lo que las variables estáticas inyectadas directamente en el método estático son en realidad nulas.
Pensando:
- Sigue siendo el problema del ciclo de vida de Spring Bean
- Y el orden de carga: Constructor (método de construcción) -> @Autowired (inyección de dependencia) -> @PostConstruct (método anotado) problema
El ciclo de vida de Spring Bean:
La creación de instancias y la asignación de propiedades corresponden a la inyección de métodos de constructor y establecedor, la inicialización y destrucción son dos etapas que los usuarios pueden personalizar y extender
- Instanciación
- Asignación de atributos Rellenar
- Inicialización
- Destrucción
Inicialización ==> 4 métodos de transformación de objetos Bean:
Cuándo llamar a la fase de Destrucción:
- Instancia única: cuando el contenedor está cerrado
- Múltiples instancias: el contenedor no administrará este Bean y no llamará a su método de destrucción.
Solución uno:
@Autowired se usa en el constructor
Sabemos que la anotación @Autowired puede anotar variables de miembro de clase, métodos y constructores para completar el trabajo de ensamblaje automático, de esta manera se usa @Autowired en el constructor.
@Component public class ScriptExecuteContent { private static SignRepository signRepository; @Autowired public ScriptExecuteContent(SignRepository signRepository) { ScriptExecuteContent.signRepository = signRepository; } public static String checkSign(String certNo, String acctNo, String instCode) { Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode); if (null != sign && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code()) && DateUtil.getCurrentDate().before(sign.getExpireTime())) { return "1"; } else { return "0"; } } }
Solución dos:
Utilice la anotación @PostConstruct
- A partir de la especificación Java EE5, se han agregado dos anotaciones que afectan el ciclo de vida de Servlet a Servlet, @PostConstruct y @PreDestroy
- Explicación de esta anotación en Java: @PostConstruct Esta anotación se encuentra en el paquete javax.annotation y se utiliza para decorar un método void () no estático
- El método modificado por @PostConstruct se ejecutará cuando el servidor cargue el Servlet, y el servidor solo lo ejecutará una vez.
- El método modificado por @PostConstruct se ejecuta después del constructor y antes del método init ()
- El método @PreDestroy () se ejecuta después de que se ejecuta el método destroy ()
- @PostConstruct reglas de anotación: Excepto por el caso especial de interceptor, no se permiten parámetros en otros casos, de lo contrario, el marco de primavera informará IllegalStateException; y si el valor de retorno es nulo, en realidad puede tener un valor de retorno, al menos no lo hará reportar un error, solo será ignorado
- Por lo general, usamos el método de anotación @PostConstruct en el marco de Spring para anotar el orden de ejecución del método de anotación en toda la inicialización del Bean: Constructor (método de construcción) -> @Autowired (inyección de dependencia) -> @PostConstruct (método anotado)
@Component public class ScriptExecuteContent { @Autowired private SignRepository signRepository; private static ScriptExecuteContent scriptExecuteContent; @PostConstruct public void update() { scriptExecuteContent = this; scriptExecuteContent.signRepository = this.signRepository; } public static String checkSign(String certNo, String acctNo, String instCode) { Sign sign = scriptExecuteContent.signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode); if (null != sign && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code()) && DateUtil.getCurrentDate().before(sign.getExpireTime())) { return "1"; } else { return "0"; } } }
Ejemplo 2:
@Component public class StaticBook { private static String url; @Value("${test.str}") private String str; @PostConstruct public void update() { this.url = this.str; } public static BookTestTemp getValue(){ return new BookTestTemp(1, "bookName", "123", url); } }