JavaRush /Blog Java /Random-ES /La primavera es para los perezosos. Fundamentos, concepto...
Стас Пасинков
Nivel 26
Киев

La primavera es para los perezosos. Fundamentos, conceptos básicos y ejemplos con código. Parte 2

Publicado en el grupo Random-ES
En el último artículo , expliqué en pocas palabras qué es la primavera, qué son los contenedores y su contexto. Ahora es el momento de probar cómo funciona todo. La primavera es para los perezosos.  Fundamentos, conceptos básicos y ejemplos con código.  Parte 2 - 1Lo haré yo mismo en Intellij Idea Enterprise Edition. Pero todos mis ejemplos también deberían funcionar en la edición gratuita Intellij Idea Community Edition. Sólo si ves en las capturas de pantalla que tengo algún tipo de ventana que tú no tienes, no te preocupes, no es crítico para este proyecto :) Primero, creemos un proyecto Maven vacío. Mostré cómo hacer esto en el artículo (lea hasta las palabras " Es hora de convertir nuestro proyecto maven en un proyecto web ", después de eso ya muestra cómo crear un proyecto web, y no lo necesitamos ahora) Creémoslo en la carpeta src/main /java es algún paquete (en mi caso lo llamé " ru.javarush.info.fatfaggy.animals", puedes nombrarlo como quieras, pero no olvides reemplazarlo con tu nombre en los lugares correctos). Y creemos una clase Mainen la que haremos un método.
public static void main(String[] args) {
    ...
}
Luego abra el archivo pom.xml y agregue una sección allí dependencies. Ahora vamos al repositorio de Maven y buscamos allí el contexto de primavera de la última versión estable, y pegamos lo que obtuvimos dentro de la sección dependencies. Describí este proceso con un poco más de detalle en este artículo (consulte la sección " Conexión de dependencias en Maven "). Luego, Maven buscará y descargará las dependencias necesarias y, al final, debería obtener algo como esto:
La primavera es para los perezosos.  Fundamentos, conceptos básicos y ejemplos con código.  Parte 2 - 2
En la ventana de la izquierda puedes ver la estructura del proyecto con el paquete y la clase Main. La ventana del medio muestra cómo se ve mi pom.xml. También agregué una sección de propiedades allí , en la que le indiqué a Maven qué versión de Java estaba usando en el código fuente y en qué versión compilar. Esto es solo para que no se me ocurra una advertencia al iniciar que se está utilizando una versión antigua de Java. Puedes hacerlo, no puedes) En la ventana derecha, puedes ver que aunque conectamos solo el contexto de primavera, automáticamente agregó core, beans, aop y expresión. Era posible conectar cada módulo por separado, registrando una dependencia para cada uno en la memoria con una indicación explícita de la versión, pero por ahora estamos contentos con la opción tal como está ahora. Ahora creemos un paquete entities(entidades) y creemos 3 clases en él: Cat, Dog, Parrot. Deje que cada animal tenga un nombre ( private String name, puede codificar algunos valores allí), y los captadores/definidores son públicos. Ahora ve a la clase Mainy main()escribe algo como esto en el método:
public static void main(String[] args) {
	// crea un contexto de primavera vacío que buscará sus beans mediante anotaciones en el paquete especificado
	ApplicationContext context =
		new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.entities");

	Cat cat = context.getBean(Cat.class);
	Dog dog = (Dog) context.getBean("dog");
	Parrot parrot = context.getBean("parrot-kesha", Parrot.class);

	System.out.println(cat.getName());
	System.out.println(dog.getName());
	System.out.println(parrot.getName());
}
Primero, creamos un objeto de contexto y en el constructor le damos el nombre del paquete que debe analizarse en busca de beans. Es decir, Spring revisará este paquete e intentará encontrar clases que estén marcadas con anotaciones especiales que le permitan a Spring saber que se trata de un bean. Después de lo cual crea objetos de estas clases y los coloca en su contexto. Después de lo cual obtenemos un gato de este contexto. Al abordar el objeto de contexto, le pedimos que nos proporcione un bean (objeto) e indique qué clase de objeto necesitamos (aquí, por cierto, puede especificar no solo clases, sino también interfaces). Después de lo cual Spring nos devuelve un objeto de esta clase, que guardamos en una variable. A continuación, le pedimos a Spring que nos consiga un frijol llamado "perro". Cuando Spring crea un objeto de clase, Dogle dará un nombre estándar (si el nombre del bean que se está creando no se especifica explícitamente), que es el nombre de la clase del objeto, solo que con una letra minúscula. Por lo tanto, dado que nuestra clase se llama Dog, el nombre de dicho frijol será "perro". Si tuviéramos un objeto allí BufferedReader, Spring le daría el nombre predeterminado "bufferedReader". Y dado que en este caso (en Java) no hay una certeza exacta de qué clase será dicho objeto, simplemente devuelve uno determinado Object, que luego convertimos manualmente al tipo que necesitamos Dog. Es más conveniente la opción con una indicación explícita de la clase. Bueno, en el tercer caso obtenemos un frijol por clase y nombre. Simplemente puede surgir una situación en la que en el contexto habrá varios beans de la misma clase y, para indicar qué frijol en particular necesitamos, indicamos su nombre. Como aquí también indicamos claramente la clase, ya no tenemos que emitir. ¡Importante!Si resulta que Spring encuentra varios beans de acuerdo con los requisitos que le especificamos, no podrá determinar qué bean darnos y lanzará una excepción. Por lo tanto, trate de indicarle con la mayor precisión posible qué contenedor necesita para que no surjan situaciones de este tipo. Si Spring no encuentra un solo bean en su contexto de acuerdo con sus condiciones, también generará una excepción. Bueno, entonces simplemente mostramos los nombres de nuestros animales en la pantalla para asegurarnos de que son exactamente los objetos que necesitamos. Pero si ejecutamos el programa ahora, veremos que Spring jura que no puede encontrar los animales que necesitamos en su contexto. Esto sucedió porque él no creó estos frijoles. Como ya dije, cuando Spring escanea clases, busca "sus" anotaciones de Spring allí. Y si no lo encuentra, entonces no percibe esas clases como aquellas cuyos beans necesita crear. Para solucionar este problema, simplemente agregue una anotación @Componentdelante de la clase en nuestras clases de animales.
@Component
public class Cat {
	private String name = "Barsik";
	...
}
Pero eso no es todo. Si necesitamos indicarle explícitamente a Spring que el bean de esta clase debe tener un nombre específico, este nombre se puede indicar entre paréntesis después de la anotación. Por ejemplo, para que Spring le dé el nombre que necesitamos parrot-keshaal contenedor de loros, del cual mainluego recibiremos este loro, debemos hacer algo como esto:
@Component("parrot-kesha")
public class Parrot {
	private String name = "kesha";
	...
}
Este es el objetivo de la configuración automática . Usted escribe sus clases, las marca con las anotaciones necesarias y le indica a Spring un paquete con sus clases, a través del cual pasa, busca anotaciones y crea objetos de dichas clases. Por cierto, Spring buscará no solo las anotaciones @Component, sino también todas las demás anotaciones heredadas de ésta. Por ejemplo, @Controller, @RestController, @Servicey @Repositoryotros, que veremos en próximos artículos. Ahora intentemos hacer lo mismo, pero usando la configuración de Java . Primero, eliminemos las anotaciones @Componentde nuestras clases. Para complicar la tarea, imaginemos que estas no son nuestras propias clases escritas por nosotros mismos, que podemos modificar fácilmente, agregar algo, incluidas anotaciones. Es como si estas clases estuvieran guardadas en alguna biblioteca. En este caso, no podemos editar estas clases de ninguna manera para que Spring las acepte. ¡Pero necesitamos objetos de estas clases! Aquí necesitaremos la configuración de Java para crear dichos objetos. Para empezar, creemos un paquete, por ejemplo configs, y en él, una clase Java normal, por ejemplo, MyConfigy márquelo con una anotación.@Configuration
@Configuration
public class MyConfig {
}
Ahora necesitamos modificar ligeramente main()la forma en que creamos el contexto en el método. Podemos especificar directamente nuestra clase con la configuración allí:
ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class);
Si tenemos varias clases diferentes donde creamos beans y queremos conectar varias de ellas a la vez, simplemente las indicamos ahí separadas por comas:
ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
Pues si tenemos demasiados y queremos conectarlos todos a la vez simplemente indicamos aquí el nombre del paquete en el que los tenemos:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.configs");
En este caso, Spring revisará este paquete y encontrará todas las clases marcadas con la anotación @Configuration. Bueno, en caso de que tengamos un programa realmente grande donde las configuraciones están divididas en diferentes paquetes, simplemente indicamos los nombres de los paquetes con las configuraciones separadas por comas:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals.database.configs",
		"ru.javarush.info.fatfaggy.animals.root.configs",
		"ru.javarush.info.fatfaggy.animals.web.configs");
Bueno, o el nombre de un paquete más común a todos ellos:
ApplicationContext context =
	new AnnotationConfigApplicationContext("ru.javarush.info.fatfaggy.animals");
Puedes hacerlo como quieras, pero me parece que la primera opción, donde simplemente especificas una clase con configuraciones, se adaptará mejor a nuestro programa. Al crear un contexto, Spring buscará aquellas clases que estén marcadas con la anotación @Configurationy creará objetos de estas clases en sí mismo. Después de lo cual intentará llamar a métodos en estas clases que están marcadas con la anotación @Bean, lo que significa que dichos métodos devolverán beans (objetos) que ya ha colocado en su contexto. Bueno, ahora creemos frijoles para gatos, perros y loros en nuestra clase con configuración de Java. Esto se hace de forma muy sencilla:
@Bean
public Cat getCat() {
	return new Cat();
}
Resulta que nosotros mismos creamos nuestro gato manualmente y se lo dimos a Spring, y él ya colocó este objeto nuestro en su contexto. Como no especificamos explícitamente el nombre de nuestro bean, Spring le dará al bean el mismo nombre que el nombre del método. En nuestro caso, la haba de gato tendrá el nombre " getCat". Pero como en main-e todavía obtenemos el gato no por nombre, sino por clase, entonces, en este caso, el nombre de este contenedor no es importante para nosotros. Haga un frijol con un perro de la misma manera, pero tenga en cuenta que Spring nombrará dicho frijol por el nombre del método. Para nombrar explícitamente nuestro frijol con el loro, simplemente indique su nombre entre paréntesis después de la anotación @Bean:
@Bean("parrot-kesha")
public Object weNeedMoreParrots() {
	return new Parrot();
}
Como puede ver, aquí indiqué el tipo de valor de retorno Objecty llamé al método cualquier cosa. Esto no afecta el nombre del bean de ninguna manera porque lo configuramos explícitamente aquí. Pero es mejor indicar el tipo de valor de retorno y el nombre del método no de la nada, sino más o menos claramente. Incluso para ti, cuando abras este proyecto dentro de un año. :) Ahora consideremos una situación en la que para crear un bean necesitamos usar otro bean . Por ejemplo, queremos que el nombre del gato en cat bean esté formado por el nombre del loro y la cadena "-killer". ¡Ningún problema!
@Bean
public Cat getCat(Parrot parrot) {
	Cat cat = new Cat();
	cat.setName(parrot.getName() + "-killer");
	return cat;
}
Aquí Spring verá que antes de crear este bean, deberá transferir aquí el frijol loro ya creado. Por lo tanto, construirá una cadena de llamadas a nuestros métodos para que primero se llame al método para crear un loro y luego pase este loro al método para crear un gato. Aquí es donde funcionó lo llamado inyección de dependencia : el propio Spring pasó el parrot bean requerido a nuestro método. Si la idea se queja de una variable parrot, no olvides cambiar el tipo de retorno en el método para crear un loro de Objecta Parrot. Además, la configuración de Java le permite ejecutar absolutamente cualquier código Java en métodos para crear beans. Realmente puedes hacer cualquier cosa: crear otros objetos auxiliares, llamar a cualquier otro método, incluso aquellos que no están marcados con anotaciones de resorte, crear bucles, condiciones, ¡lo que se te ocurra! Todo esto no se puede lograr mediante la configuración automática, y mucho menos utilizando configuraciones xml. Ahora veamos un problema más divertido. Con polimorfismo e interfaces :) Creemos una interfaz WeekDayy creemos 7 clases que implementarían esta interfaz: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday. Creemos un método en la interfaz String getWeekDayName()que devolvería el nombre del día de la semana de la clase correspondiente. Es decir, la clase Mondaydevolvería " monday", etc. Digamos que la tarea al iniciar nuestra aplicación es colocar un bean en el contexto que correspondería al día de la semana actual. No todos los beans de todas las clases que implementan WeekDayla interfaz, sino solo el que necesitamos. Se puede hacer algo como esto:
@Bean
public WeekDay getDay() {
	DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
	switch (dayOfWeek) {
		case MONDAY: return new Monday();
		case TUESDAY: return new Tuesday();
		case WEDNESDAY: return new Wednesday();
		case THURSDAY: return new Thursday();
		case FRIDAY: return new Friday();
		case SATURDAY: return new Saturday();
		default: return new Sunday();
	}
}
Aquí el tipo de valor de retorno es nuestra interfaz, y el método devuelve objetos reales de las clases de implementación de la interfaz según el día actual de la semana. Ahora en el método main()podemos hacer esto:
WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("It's " + weekDay.getWeekDayName() + " today!");
Me dijo que hoy es domingo :) Estoy seguro de que si ejecuto el programa mañana, aparecerá un objeto completamente diferente en el contexto. Tenga en cuenta que aquí obtenemos el bean simplemente mediante la interfaz: context.getBean(WeekDay.class). Spring buscará en su contexto cuál de sus beans implementa dicha interfaz y la devolverá. Bueno, entonces resulta que WeekDayhay un objeto de tipo en una variable de tipo Sunday, y el polimorfismo, que ya todos conocemos, comienza cuando se trabaja con esta variable. :) Y unas pocas palabras sobre el enfoque combinado , donde algunos de los beans son creados por el propio Spring, mediante el escaneo de paquetes para detectar la presencia de clases con una anotación @Component, y algunos otros beans se crean usando la configuración de Java. Para hacer esto, volvamos a la versión original, cuando las clases Catestaban Dogmarcadas Parrotcon una anotación @Component. Digamos que queremos crear contenedores para nuestros animales usando el escaneo automático del paquete entitiespara la primavera, pero creamos un contenedor con el día de la semana como acabamos de hacer. Todo lo que necesita hacer es agregar en el nivel de clase MyConfig, que especificamos al crear el contexto en mainla anotación -ésima @ComponentScan, e indicar entre paréntesis el paquete que necesita ser escaneado y los beans de las clases necesarias creados automáticamente:
@Configuration
@ComponentScan("ru.javarush.info.fatfaggy.animals.entities")
public class MyConfig {
	@Bean
	public WeekDay getDay() {
		DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
		switch (dayOfWeek) {
			case MONDAY: return new Monday();
			case TUESDAY: return new Tuesday();
			case WEDNESDAY: return new Wednesday();
			case THURSDAY: return new Thursday();
			case FRIDAY: return new Friday();
			case SATURDAY: return new Saturday();
			default: return new Sunday();
		}
	}
}
Resulta que al crear un contexto, Spring ve que necesita procesar la clase MyConfig. Entra y ve que necesita escanear el paquete " ru.javarush.info.fatfaggy.animals.entities" y crear beans de esas clases, después de lo cual ejecuta un método getDay()de la clase MyConfigy agrega un bean de ese tipo WeekDaya su contexto. En el método, main()ahora tenemos acceso a todos los beans que necesitamos: tanto los objetos animales como el bean del día de la semana. Cómo asegurarse de que Spring también recoja algunas configuraciones xml: búsquelo usted mismo en Internet si lo necesita :) Resumen:
  • intente utilizar la configuración automática;
  • durante la configuración automática, indicamos el nombre del paquete que contiene las clases cuyos beans se deben crear;
  • dichas clases están marcadas con una anotación@Component;
  • la primavera pasa por todas esas clases, crea sus objetos y los coloca en el contexto;
  • si por algún motivo la configuración automática no nos conviene, utilizamos la configuración de Java;
  • en este caso, creamos una clase Java normal cuyos métodos devolverán los objetos que necesitamos y marcamos dicha clase con una anotación @Configurationen caso de que analicemos todo el paquete en lugar de especificar una clase específica con configuración al crear el contexto;
  • Los métodos de esta clase que devuelven beans están marcados con la anotación @Bean;
  • Si queremos habilitar el escaneo automático cuando usamos la configuración de Java, usamos la anotación @ComponentScan.
Si no queda nada claro, intenta leer este artículo en un par de días. Bueno, o si estás en los primeros niveles de Javarash, entonces quizás sea un poco pronto para que aprendas la primavera. Siempre puedes volver a este artículo un poco más tarde, cuando te sientas más seguro programando en Java. Si todo está claro, puedes intentar transferir algunos de tus proyectos favoritos a Spring :) Si algo está claro, pero algo no tanto, por favor comenta :) También hay sugerencias y comentarios si entré en algún lugar o escribí algo estúpido ) En el próximo artículo, profundizaremos en spring-web-mvc y crearemos una aplicación web sencilla utilizando spring.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION