Anotación de modo
El modo de anotación estereotipo conocido como anotaciones, notas de primavera tiene en modo común @Service
, @Repository
, @Controller
y así sucesivamente, que se "deriva" de @Component
comentarios. Todos sabemos que todas las @Component
clases anotadas serán escaneadas por Spring e incluidas en el contenedor IOC, y @Component
las clases anotadas por las anotaciones derivadas también serán escaneadas en el contenedor IOC. A continuación, llegamos a comprender principalmente @Component
la "derivación" y las "capas" a través de anotaciones de modo personalizado .
@Componente "Derivado"
Cree un nuevo proyecto de Spring Boot, la versión de Spring Boot es 2.1.0.RELEASE, artifactId
autoconfig y se introducen las spring-boot-starter-web
dependencias. La estructura del proyecto es la siguiente:
En com.example.demo
caso de que el nuevo annotation
paquete, y luego cree un FirstLevelService
comentario:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface FirstLevelService {
String value() default "";
}
Esta anotación está definida por @Service
anotaciones, @Service
y encontrará que está @Component
anotada cuando ve el código fuente , por lo que su relación jerárquica es:
└─ @ Componente
└─ @ Servicio
└─ @ FirstLevelService
Eso @FirstLevelService
se @Component
deriva del modo de anotación, tenemos que probar si se marcó una clase que se puede escanear en el contenedor IOC:
En com.example.demo
Nuevo bajo service
el paquete, y luego cree una TestService
clase:
@SecondLevelService
public class TestService {
}
En com.example.demo
el nuevo bootstrap
paquete, y luego cree una ServiceBootStrap
clase para el registro de prueba TestService
y consígala del buque del COI:
@ComponentScan("com.example.demo.service")
public class ServiceBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(ServiceBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
TestService testService = context.getBean("testService", TestService.class);
System.out.println("TestService Bean: " + testService);
context.close();
}
}
Ejecute el método principal de esta clase, la salida de la consola es la siguiente:
@Componente "jerárquico"
Creamos com.example.demo.annotation
otra SecondLevelService
definición de anotación debajo de la ruta , la anotación está @FirstLevelService
marcada por lo anterior :
En este momento, la relación jerárquica es:
└─ @ Componente
└─ @ Servicio
└─ @ FirstLevelService
└─ @ SecondLevelService
Reemplazaremos la TestService
anotación anterior con el método principal @SecondLevelService
y luego lo ejecutaremos nuevamente ServiceBootStrap
, el resultado es el siguiente:
Se puede ver que el resultado también es exitoso.
Una cosa a tener en cuenta aquí es que la
@Component
anotación solo contiene una definición de atributo de valor, por lo que su anotación "derivada" solo puede contener una definición de atributo de valor.
Controlador de módulo @Enable
@Enable
Los controladores de módulo son compatibles después de Spring Framework 3.1. En general, el módulo aquí es una colección de componentes para lograr una determinada función. A través del @Enable
controlador del módulo, podemos activar la función del módulo correspondiente.
@Enable
La unidad de módulo se puede dividir en dos modos de implementación: "unidad de anotación" y "programación de interfaz". La siguiente es una demostración una por una:
Basado en anotaciones
En Spring, se puede ver un ejemplo basado en anotaciones desde el @EnableWebMvc
código fuente:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}
Esta anotación se realiza @Import
importando una clase de configuración DelegatingWebMvcConfiguration
:
Esta clase de configuración se hereda de ella WebMvcConfigurationSupport
, que define algunas declaraciones de Bean.
Por lo tanto, el controlador de
@Enable
módulo controlado por anotaciones realmente@Import
importa una clase de configuración para realizar el registro de componentes del módulo correspondiente.Cuando estos componentes se registran en el contenedor IOC, se puede utilizar la función correspondiente de este módulo.
Definamos un @Enable
controlador de módulo basado en anotaciones .
En com.example.demo
New Under configuration
the package, y luego cree una HelloWorldConfiguration
clase de configuración:
@Configuration
public class HelloWorldConfiguration {
@Bean
public String hello() {
return "hello world";
}
}
Un hello
Bean con nombre se define en esta clase de configuración con contenido hello world
.
Al com.example.demo.annotation
crear una siguiente EnableHelloWorld
definición de anotación:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(HelloWorldConfiguration.class)
public @interface EnableHelloWorld {
}
@Import
Importamos la clase de configuración que acabamos de crear en esta clase de anotación .
Luego, al com.example.demo.bootstrap
crear una próxima TestEnableBootstap
clase de inicio para probar, la @EnableHelloWorld
anotación está en vigor:
@EnableHelloWorld
public class TestEnableBootstap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(TestEnableBootstap.class)
.web(WebApplicationType.NONE)
.run(args);
String hello = context.getBean("hello", String.class);
System.out.println("hello Bean: " + hello);
context.close();
}
}
Ejecute el método principal de esta clase, la salida de la consola es la siguiente:
Explique que nuestro sistema de anotaciones personalizado @EnableHelloWorld
es factible.
Programación de interfaz
Además de utilizar el método anterior, también podemos implementar la @Enable
unidad de módulo mediante la programación de la interfaz . En Spring, hay @EnableCaching
anotaciones basadas en la programación de la interfaz , verifique el código fuente:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({CachingConfigurationSelector.class})
public @interface EnableCaching {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default 2147483647;
}
EnableCaching
Las anotaciones @Import
importan una CachingConfigurationSelector
clase, que indirectamente implementa la ImportSelector
interfaz.En el estudio en profundidad del registro de componentes de Spring , hemos introducido que el ImportSelector
registro de componentes se puede lograr a través de .
Por lo tanto
@Enable
, la esencia de implementar la conducción de módulos a través de la programación de la interfaz es@Import
importar laImportSelector
clase de implementación de la interfaz , que puede definir los componentes que deben registrarse en el contenedor IOC, para realizar el registro de los componentes correspondientes del módulo correspondiente.
A continuación, nos volvemos a dar cuenta de ello de acuerdo con esta idea:
En com.example.demo
el nuevo selector
paquete, luego una nueva ruta en las interfaces HelloWorldImportSelector
implementadas ImportSelector
:
public class HelloWorldImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{HelloWorldConfiguration.class.getName()};
}
}
Si no comprende el significado del código anterior, puede leer el artículo sobre el aprendizaje en profundidad del registro de componentes de Spring .
Luego modificamos EnableHelloWorld
:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(HelloWorldImportSelector.class)
public @interface EnableHelloWorld {
}
La importación anterior es HelloWorldImportSelector
, no HelloWorldConfiguration
.
Ejecute TestEnableBootstap
el método principal nuevamente y encontrará que la salida es la misma.
Montaje automático
La capa inferior de la tecnología de ensamblaje automático en Spring Boot utiliza principalmente las siguientes tecnologías:
-
Ensamblado de anotación en modo resorte
-
Montaje del módulo Spring @Enable
-
Ensamblaje condicional de Spring (introducido en el estudio en profundidad del registro de componentes de Spring )
-
Mecanismo de carga de fábrica de resortes
La clase de implementación del mecanismo de carga de la fábrica Spring es SpringFactoriesLoader
, verifique su código fuente:
El método de esta clase leerá el archivo de configuración spring.factories en el directorio META-INF. Verificamos el archivo en spring-boot-autoconfigure-2.1.0.RELEASE.jar:
Cuando se @EnableAutoConfiguration
marca la clase de inicio , todas las clases en la captura de pantalla anterior serán escaneadas por Spring para ver si se pueden incluir en el contenedor IOC para su administración.
Por ejemplo org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
, el código fuente que vimos :
Se puede ver que hay algunas anotaciones marcadas en esta categoría, entre las que se @Configuration
encuentran las anotaciones de modo, la @EnableConfigurationProperties
tecnología de ensamblaje de módulos y la ConditionalOnClass
tecnología de ensamblaje condicional. Esto es consistente con las principales tecnologías subyacentes del autoensamblaje de Spring Boot enumeradas anteriormente, por lo que podemos personalizar una implementación de autoensamblaje basada en esta idea.
Cree una nueva clase de configuración HelloWorldAutoConfiguration
:
@Configuration
@EnableHelloWorld
@ConditionalOnProperty(name = "helloworld", havingValue = "true")
public class HelloWorldAutoConfiguration {
}
Luego cree un nuevo directorio META-INF en el directorio de recursos y cree un archivo spring.factories:
# Configurar automáticamente org.springframework.boot.autoconfigure.EnableAutoConfiguration = \ com.example.demo.configuration.HelloWorldAutoConfiguration
Luego agregue la helloworld=true
configuración en el archivo de configuración application.properties
hola mundo = verdadero
Finalmente cree EnableAutoConfigurationBootstrap
, pruebe HelloWorldAutoConfiguration
si funciona:
@EnableAutoConfiguration
public class EnableAutoConfigurationBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableAutoConfigurationBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
String hello = context.getBean("hello", String.class);
System.out.println("hello Bean: " + hello);
context.close();
}
}
Ejecute el método principal, la salida de la consola es la siguiente:
Demuestra que nuestro montaje automático personalizado ha tenido éxito.
A continuación se muestra un breve análisis de la lógica de ejecución del código:
-
El mecanismo de carga de fábrica de Spring leerá automáticamente el contenido del archivo spring.factories en el directorio META-INF;
- Definimos en spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration = \ com.example.demo.configuration.HelloWorldAutoConfiguration
Usamos
@EnableAutoConfiguration
anotaciones en la clase de prueba , luegoHelloWorldAutoConfiguration
Spring lo escaneará para ver si cumple con los requisitos, y si cumple con los requisitos, se incluirá en el contenedor IOC;
-
HelloWorldAutoConfiguration
La función de la@ConditionalOnProperty
anotación anterior es: cuando se configura en el archivo de configuraciónhelloworld=true
(agregamos esta configuración, por lo que cumple con los requisitos), esta clase cumple con las reglas de escaneo; la@EnableHelloWorld
anotación es una anotación personalizada impulsada por un módulo en nuestro ejemplo anterior, que introduce el hello Bean, por lo que el hello bean existirá en el contenedor IOC; -
A través de los pasos anteriores, podemos obtener el bean hello a través del contexto.