Introducción a Spring Boot, Parte 8 Configuración de beans en Spring
15/03/2021
Autor / Editor: Dr. Dirk Koller / Stephan Augsten
El contenedor de inyección de dependencia está en el corazón de Spring. Esto puede administrar varios componentes, incluidos, por supuesto, Java Beans. Estos beans se configuran de manera contemporánea y con seguridad de tipos utilizando una clase Java.
Empresas sobre el tema
Se supone que nuestro bean de ejemplo aquí es un DatabasePersister, es decir, una clase que almacena datos en una base de datos. Debido a que nuestra aplicación hipotética podría tener diferentes tipos de almacenamiento, como FilesystemPersister o CloudPersister, la clase implementa la interfaz Persister con el método persistente:
interfaz pública Persister { public void persist();}
La clase pública DatabasePersister implementa Persister {
@Override public void persistir() { System.out.println("In DatabasePersister persistir"); }}
Tutorial de botas de primavera
Galería de imágenes con 20 imágenes
Configuración en la clase Java
El persistente de la base de datos debe inyectarse en otra clase, por lo que debe informarse al contenedor. Esto se hace en una clase de Java indicada por la anotación @Configuration y que normalmente termina en Config. Internamente, esta clase está marcada con @Component y, por lo tanto, se encuentra y evalúa durante el escaneo de componentes:
@Configurationpublic clase PersisterConfig {
}
En la clase, los diferentes beans ahora están disponibles a través de métodos de definición de beans y están marcados con la anotación @Bean:
@Configurationpublic clase PersisterConfig {
@Bean public Persister databasePersister() { return new DatabasePersister(); }}
La configuración también posible de componentes con la ayuda de XML ya no es común hoy en día, pero todavía se encuentra a menudo en proyectos existentes.
Inyectando los frijoles
Un bean configurado de esta manera ahora se puede inyectar con Autowired como de costumbre, por ejemplo, en un servicio. Idealmente, el servicio no conoce el persistente específico, funciona con la interfaz y llama al método persistente definido allí:
@Servicepublic clase PersisterService {
Persistente privado de @Autowired persistente;
public void persistData() { persister.persist(); }}
El contenedor ahora busca un bean con el tipo correcto, es decir, persistente, en los componentes existentes cuando se inicia y encuentra el DatabasePersister configurado. Debido a la implementación de la interfaz, es un persistente y se usa como candidato para inyección.
Al encontrar problemas, a veces es útil tirar los frijoles en el contenedor. El método de ejecución de la clase SpringApplication en la clase principal devuelve un ApplicationContext que permite el acceso a los beans configurados o sus nombres a través del método getBeanDefinitionNames():
@SpringBootApplicationclase pública Aplicación de demostración {
applicationContext privado estático ApplicationContext; public static void main(String[] args) { applicationContext = SpringApplication.run(DemoApplication.class, args);> String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String beanName: beanDefinitionNames) { System.out.println(beanName); } }}
El persistente configurado se puede encontrar en la salida de la consola junto con muchos otros beans:
...
servicio persistente
controlador de persona
perherConfig
persistencia de base de datos
...
Tienes muchas opciones
Se vuelve emocionante cuando incluye un segundo bean del mismo tipo de interfaz en la configuración, como FilesystemPersister. También implementa persistentes:
clase pública FilesystemPersister implementa Persister {
@Override public void persistir() { System.out.println("In FilesystemPersister persist"); }}
La configuración en PersisterConfig es análoga:
@Configurationpublic clase PersisterConfig {
@Bean public Persister databasePersister() { return new DatabasePersister(); }
@Bean public Persister filesystemPersister() { return new FilesystemPersister(); }}
Al inyectar el bean en el servicio, el contenedor ahora enfrenta un problema: ¿cuál de los dos persistentes debe inyectar? Spring no puede resolver el dilema por sí solo. La aplicación ya no se inicia y en su lugar informa un mensaje de error:
El persistente de campo en com.example.demo.PersisterService requería un solo bean, pero se encontraron 2: - databasePersister: definido por el método 'databasePersister' en el recurso de ruta de clase [com/example/demo/PersisterConfig.class] - filesystemPersister: definido por el método 'filesystemPersister' en el recurso de ruta de clases [com/example/demo/PersisterConfig.class]
Afortunadamente, también se incluyen posibles soluciones al problema en el mensaje:
Acción: considere marcar uno de los beans como @Primary, actualizar el consumidor para que acepte varios beans o usar @Qualifier para identificar el bean que debe consumirse
El conflicto se puede resolver mediante las anotaciones @Primary o @Qualifier. La anotación @Primary en uno (!) de los dos métodos de definición de bean significa que se prefiere el bean correspondiente. Por supuesto, la clase de configuración debe ser accesible para esto. Este no es siempre el caso cuando se utilizan bibliotecas externas.
Una alternativa es la anotación @Qualifier, que se puede adjuntar al punto de inyección, es decir, a la clase de uso. Al especificar el nombre del método, se da preferencia a FilesystemPersister en PersisterService:
@Servicepublic clase PersisterService {
@Qualifier("filesystemPersister") @Autowired privado Persister persistente;
public void persistData() { persister.persist(); }}
Tutorial de botas de primavera
Galería de imágenes con 20 imágenes
En otra clase, sin embargo, se puede preferir DatabasePersister. Este patrón se encuentra a menudo al configurar varias fuentes de datos.
En la próxima parte de la serie Spring Boot, veremos las diferentes formas en que Spring Boot puede inyectar beans. Spoiler: la inyección de campo utilizada aquí es adecuada para artículos de blog, pero en la práctica es solo una segunda opción.
(ID:47119037)