Annotation de mode
Stéréotype mode Annotation connu sous forme d' annotations, les notes de printemps ont en mode commun @Service
, @Repository
, @Controller
et ainsi de suite, ils sont « dérivés » de @Component
commentaires. Nous savons tous que toutes les @Component
classes annotées seront scannées par Spring et incluses dans le conteneur IOC, et @Component
les classes annotées par les annotations dérivées seront également scannées dans le conteneur IOC. Ci-dessous, nous arrivons principalement à comprendre @Component
la «dérivation» et la «superposition» à travers les annotations en mode personnalisé .
@Component "Dérivée"
Créez un nouveau projet Spring Boot, la version Spring Boot est 2.1.0.RELEASE, la artifactId
configuration automatique et les spring-boot-starter-web
dépendances sont introduites . La structure du projet est la suivante:
Dans le com.example.demo
cas du nouveau annotation
package, puis créez un FirstLevelService
commentaire:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
public @interface FirstLevelService {
String value() default "";
}
Cette annotation est définie par des @Service
annotations, @Service
et vous constaterez qu'elle est @Component
annotée lorsque vous affichez le code source , de sorte que leur relation hiérarchique est:
└─ @ Composant
└─ @ Service
└─ @ FirstLevelService
Cela @FirstLevelService
est @Component
dérivé du mode d'annotation, nous devons tester si elle a marqué une classe peut être scannée dans le conteneur IOC:
Dans com.example.demo
Nouveau sous service
le package, puis créez une TestService
classe:
@SecondLevelService
public class TestService {
}
Dans com.example.demo
le nouveau bootstrap
package, puis créez une ServiceBootStrap
classe pour le registre de test TestService
et obtenez-la du navire du CIO:
@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();
}
}
Exécutez la méthode principale de cette classe, la sortie de la console est la suivante:
@Component "hiérarchique"
Nous com.example.demo.annotation
créons une autre SecondLevelService
définition d'annotation sous le chemin , l'annotation est @FirstLevelService
marquée par ce qui précède :
À ce stade, la relation hiérarchique est:
└─ @ Component
└─ @ Service
└─ @ FirstLevelService
└─ @ SecondLevelService
Nous remplacerons l' TestService
annotation ci - dessus par la méthode principale, @SecondLevelService
puis la réexécuterons ServiceBootStrap
, le résultat est le suivant:
On voit que le résultat est également réussi.
Une chose à noter ici est que l'
@Component
annotation ne contient qu'une seule définition d'attribut de valeur, de sorte que son annotation «dérivée» ne peut contenir qu'une seule définition d'attribut de valeur.
@Activer le pilote du module
@Enable
Les pilotes de module sont pris en charge après Spring Framework 3.1. En général, le module est ici un ensemble de composants pour réaliser une certaine fonction. Grâce au @Enable
pilote de module, nous pouvons activer la fonction de module correspondante.
@Enable
L'entraînement du module peut être divisé en deux modes d'implémentation: «entraînement d'annotation» et «programmation d'interface». Voici une démonstration un par un:
Piloté par les annotations
Dans Spring, un exemple basé sur les annotations peut être visualisé à partir du @EnableWebMvc
code source:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}
Cette annotation se fait en @Import
important une classe de configuration DelegatingWebMvcConfiguration
:
Cette classe de configuration en est héritée WebMvcConfigurationSupport
, ce qui définit certaines déclarations Bean.
Par conséquent, le
@Enable
pilote de module piloté par annotations@Import
importe en fait une classe de configuration pour réaliser l'enregistrement des composants du module correspondant.Lorsque ces composants sont enregistrés dans le conteneur IOC, la fonction correspondante de ce module peut être utilisée.
Définissons un @Enable
pilote de module basé sur des annotations .
Dans com.example.demo
Nouveau sous configuration
le package, puis créez une HelloWorldConfiguration
classe de configuration:
@Configuration
public class HelloWorldConfiguration {
@Bean
public String hello() {
return "hello world";
}
}
Un hello
Bean nommé est défini dans cette classe de configuration avec le contenu hello world
.
Lors de la com.example.demo.annotation
création d'une prochaine EnableHelloWorld
définition d'annotation:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(HelloWorldConfiguration.class)
public @interface EnableHelloWorld {
}
Nous avons @Import
importé la classe de configuration que nous venons de créer sur cette classe d' annotation .
Ensuite, lors de la com.example.demo.bootstrap
création d'une prochaine TestEnableBootstap
classe de démarrage pour tester l' @EnableHelloWorld
annotation est en vigueur:
@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();
}
}
Exécutez la méthode principale de cette classe, la sortie de la console est la suivante:
Expliquez que notre fonction d'annotation personnalisée @EnableHelloWorld
est faisable.
Programmation d'interface
En plus d'utiliser la méthode ci-dessus, nous pouvons également implémenter le @Enable
lecteur de module via la programmation d'interface . Au printemps, il existe des @EnableCaching
annotations basées sur la programmation d'interface , vérifiez le code source:
@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
Les annotations @Import
importent une CachingConfigurationSelector
classe, qui implémente indirectement l' ImportSelector
interface.Dans l' étude approfondie de l'enregistrement des composants Spring , nous avons introduit que l' ImportSelector
enregistrement des composants peut être réalisé via .
Par conséquent
@Enable
, l'essence de la mise en œuvre du pilotage de module via la programmation d'interface est@Import
d'importer laImportSelector
classe d'implémentation d' interface , qui peut définir les composants qui doivent être enregistrés dans le conteneur IOC, afin de réaliser l'enregistrement des composants correspondants du module correspondant.
Ensuite, on en vient à le réaliser à nouveau selon cette idée:
Dans com.example.demo
le nouveau selector
paquet, puis un nouveau chemin dans les interfaces HelloWorldImportSelector
implémentées ImportSelector
:
public class HelloWorldImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{HelloWorldConfiguration.class.getName()};
}
}
Si vous ne comprenez pas la signification du code ci-dessus, vous pouvez lire l' article sur l' apprentissage approfondi de l'enregistrement des composants Spring .
Puis on modifie EnableHelloWorld
:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(HelloWorldImportSelector.class)
public @interface EnableHelloWorld {
}
L'importation ci-dessus ne l'est HelloWorldImportSelector
pas HelloWorldConfiguration
.
Exécutez à nouveau la TestEnableBootstap
méthode principale et vous constaterez que la sortie est la même.
Assemblage automatique
La couche inférieure de la technologie d'assemblage automatique de Spring Boot utilise principalement les technologies suivantes:
-
Assemblage d'annotation en mode ressort
-
Assemblage du module Spring @Enable
-
Assemblage conditionnel Spring (introduit dans l'étude approfondie de l'enregistrement des composants Spring )
-
Mécanisme de chargement d'usine à ressort
La classe d'implémentation du mécanisme de chargement d'usine Spring est SpringFactoriesLoader
, vérifiez son code source:
La méthode de cette classe lira le fichier de configuration spring.factories sous le répertoire META-INF. Nous vérifions le fichier sous spring-boot-autoconfigure-2.1.0.RELEASE.jar:
Lorsque la classe de démarrage est @EnableAutoConfiguration
marquée, toutes les classes de la capture d'écran ci-dessus seront analysées par Spring pour voir si elles peuvent être incluses dans le conteneur IOC pour la gestion.
Par exemple org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
, le code source que nous avons consulté :
On peut voir que certaines annotations sont marquées dans cette catégorie, parmi lesquelles @Configuration
les annotations de mode, la @EnableConfigurationProperties
technologie d'assemblage de module et la ConditionalOnClass
technologie d'assemblage conditionnel. Ceci est cohérent avec les principales technologies sous-jacentes de l'assemblage automatique Spring Boot répertoriées ci-dessus, nous pouvons donc personnaliser une implémentation d'assemblage automatique en fonction de cette idée.
Créez une nouvelle classe de configuration HelloWorldAutoConfiguration
:
@Configuration
@EnableHelloWorld
@ConditionalOnProperty(name = "helloworld", havingValue = "true")
public class HelloWorldAutoConfiguration {
}
Ensuite, créez un nouveau répertoire META-INF sous le répertoire resources et créez un fichier spring.factories:
# Configurer automatiquement org.springframework.boot.autoconfigure.EnableAutoConfiguration = \ com.example.demo.configuration.HelloWorldAutoConfiguration
Ajoutez ensuite la helloworld=true
configuration dans le fichier de configuration application.properties
helloworld = vrai
Enfin créez EnableAutoConfigurationBootstrap
, testez HelloWorldAutoConfiguration
si cela fonctionne:
@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();
}
}
Exécutez la méthode principale, la sortie de la console est la suivante:
Cela montre que notre assemblage automatique personnalisé a réussi.
Voici une brève analyse de la logique d'exécution du code:
-
Le mécanisme de chargement d'usine de Spring lira automatiquement le contenu du fichier spring.factories dans le répertoire META-INF;
- Nous avons défini dans spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration = \ com.example.demo.configuration.HelloWorldAutoConfiguration
Nous utilisons des
@EnableAutoConfiguration
annotations sur la classe de test , puisHelloWorldAutoConfiguration
elle sera analysée par Spring pour voir si elle répond aux exigences, et si elle répond aux exigences, elle sera incluse dans le conteneur IOC;
-
HelloWorldAutoConfiguration
La fonction de l'@ConditionalOnProperty
annotation ci - dessus est: lorsqu'elle est configurée dans le fichier de configurationhelloworld=true
(nous avons ajouté cette configuration, elle répond donc aux exigences), cette classe répond aux règles d'analyse; l'@EnableHelloWorld
annotation est une annotation personnalisée pilotée par module dans notre exemple précédent, introduit le bean hello, donc le bean hello existera dans le conteneur IOC; -
Grâce aux étapes ci-dessus, nous pouvons obtenir le bean bonjour à travers le contexte.