Reflexiones sobre el uso de JavaBean en el método estático de Java

escrito en frente

En primer lugar, el lenguaje Java no admite el uso de métodos no estáticos en métodos estáticos. La razón principal es que los métodos estáticos no tienen estado y los métodos no estáticos causarán NonPointException (este problema fallará en tiempo de compilación); El lenguaje Java restringirá directamente dicho uso.
Pero muchas veces, cuando mantenemos el código antiguo, debido a algunas limitaciones del marco, tenemos que encontrar una manera de superar esta limitación. En este momento, generalmente usamos un método de compromiso, definiendo una clase referenciada estática en la clase, y luego, anotando @PostConstructun initmétodo, asigne la clase referenciada a una instancia inyectada automáticamente en el método, y luego use la clase referenciada estática definida en el método estático. El método es el siguiente: Llame al método del objeto inyectado por @Autowired en el método estático.
Descubrí que este método sí se puede usar en el uso real, pero es limitado, es decir, se puede obtener cuando la instancia de la clase llama a este método estático, pero cuando esto Cuando la clase es una clase de herramienta, es decir, cuando normalmente usamos el nombre de la clase para llamar directamente al método estático, este método no puede funcionar. En cualquier caso, la clase de referencia que inyecta es nulo, por lo que no hay manera. Entonces solo puede introducir la clase de referencia utilizada dentro del método estático.
Podemos usar el método getBean de Spring ApplicationContext para obtener una instancia de la clase de referencia.
En una palabra, el método estático se puede llamar como un método de instancia después de que se procese el método anterior, y el método estático se puede llamar como un método de clase después de que se procese el último método.

Invocar métodos de objetos inyectados por @Autowired en métodos estáticos

Aquí hay muchos ejemplos en Internet, elegiré uno al azar.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.List;

@Service // 这里必须要有spring bean的注解,没有可以添加@component
public class DataTraceServiceImpl {
    
    

    @Autowired
    private DataTraceRepository dataTraceRepository; //自动注入引用类
    private static DataTraceRepository dataTraceRepositoryStatic; // 创建静态引用类

    @PostConstruct
    public void init() {
    
    
    	// 构造完成之后将自动注入的引用类实例赋值给静态应用类
        dataTraceRepositoryStatic = this.dataTraceRepository;
    }

    /**
     * 根据实体id查询实体的数据追溯
     * @param entityId 实体Id
     */
    public static List<DataTrace> count(Integer entityId) {
    
    
        // 这里就这么调用
        return dataTraceRepositoryStatic.findAllByEntityId(entityId);
    }

}

Este método se puede usar porque tanto la clase de la aplicación como la clase a la que se hace referencia están en el contenedor Spring Bean, y la instancia también llama a la clase de la aplicación cuando se llama al método estático. Sin embargo, al llamar con un nombre de clase más un método estático, este método no funcionará.

Introducir el objeto JavaBean dentro del método estático

Formas generales de introducir objetos JavaBean (tres)

  1. Método de inyección automática con cableado automático
  2. Formas de inyección de constructor
  3. Maneras de obtener frijoles usando ApplicationContext

Los primeros dos métodos se obtienen a nivel de clase, y el último método se puede llamar en un método.

Formas de obtener el objeto ApplicationContext

Para obtener un Bean, primero debe obtener el objeto ApplicationContext, también hay tres formas de obtenerlo: (un poco impreciso, pero de todos modos este no es el foco de nuestra atención)

  1. Método de inyección automática con cableado automático
  2. Formas de inyección de constructor
  3. Implemente la interfaz ApplicationContextAware proporcionada por Spring

Si los dos primeros aún no están disponibles, se utilizará el tercer método

import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

@Component
public class SpringContextHolder implements ApplicationContextAware {
    
    

    private ApplicationContext applicationContext;

    public void show (){
    
    
        System.out.println(applicationContext.getClass());
    }

	/**
	*    spring 在bean 初始化后会判断是不是ApplicationContextAware的子类,调用setApplicationContext()方法, 会将容器中ApplicationContext传入进去
	*/
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    
    
        this.applicationContext = applicationContext;
    }
	/**
	 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String name) {
    
    
		assertContextInjected();
		return (T) applicationContext.getBean(name);
	}

	/**
	 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
	 */
	public static <T> T getBean(Class<T> requiredType) {
    
    
		assertContextInjected();
		return applicationContext.getBean(requiredType);
	}

	/**
	 * 检查ApplicationContext不为空.
	 */
	private static void assertContextInjected() {
    
    
		Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
	}
}

Use ApplicationContext para obtener la clase en el método estático

import java.util.List;

public class DataTraceServiceImpl {
    
    
    /**
     * 根据实体id查询实体的数据追溯
     * @param entityId 实体Id
     */
    public static List<DataTrace> count(Integer entityId) {
    
    
    	DataTraceRepository service = SpringContextHolder.getBean(DataTraceRepository.class);
        
        return service.findAllByEntityId(entityId);
    }

}

Artículo de referencia: Tres formas de obtener ApplicationContext en SpringBoot
llamando al método de objeto inyectado @Autowired en el método estático

Supongo que te gusta

Origin blog.csdn.net/zhoulizhu/article/details/119031772
Recomendado
Clasificación