Ceci est le troisième volet de la série «Spring Framework 5.0 Major Changes» et les principaux changements (nouvelles fonctions et améliorations, etc.) liés aux conteneurs DI. ) Je voudrais présenter.
Dans Spring Framework 5.0, les modifications suivantes ont été apportées au conteneur DI.
Numéro d'article | Changements |
---|---|
1 | Possibilité de scanner les composants à partir du chemin de classe et d'enregistrer les beans dans le conteneur DI lorsque l'application est exécutée(@ComponentScan )Alternative à(Objectif de raccourcir et de stabiliser le temps de démarrage de l'application)En conséquence, un mécanisme pour créer un index des composants candidats à enregistrer en tant que beans lors de la compilation sera ajouté.[Vers les détails:arrow_right:] |
2 | Injection optionnelle par câblage automatique(option)Fourni à partir de votre propre bibliothèque ou d'une bibliothèque tierce pour indiquer que@Nullable Sera en mesure d'être spécifié.[Vers les détails:arrow_right:]**Note:**Le nom de l'annotation est "Nullable" Elle est jugée par si oui ou non. |
3 | GenericApplicationContext QuandAnnotationConfigApplicationContext Interface fonctionnelle(Supplier )Méthode d'enregistrement Bean utilisant(registerBean )QuandBean定義をカスタマイズするためのインタフェース(BeanDefinitionCustomizer )Sera ajouté.[Vers les détails:arrow_right:] |
4 | Lors de l'application d'AOP à une classe qui implémente une interface à l'aide de "CGLIB Proxy"(proxyTargetClass=true Lorsque spécifié)L'annotation spécifiée dans la méthode d'interface(@Transactional , @Cacheable , @Sync Tel)Sera lu.[Vers les détails:arrow_right:] |
5 | Gestion de la génération du fichier xsd spécifié lors de la définition d'un bean en XML(Fournir des fichiers xsd pour les versions antérieures)Sera aboli et seuls les fichiers xsd de cette version seront stockés dans le fichier JAR.[Vers les détails:arrow_right:] **Note:**La spécification d'un fichier xsd versionné dans un fichier XML est toujours prise en charge, mais le même fichier xsd est toujours utilisé lors de l'analyse d'un fichier XML. |
[SPR-11890]: Une fonction pour scanner la classe sous le package spécifié lorsque l'application est exécutée et enregistrer le bean dans le conteneur DI (@ ComponentScan
" ), Mais par défaut, la classe cible est recherchée à partir du chemin de classe lors de l'exécution. Avec ce mécanisme, le temps nécessaire pour analyser une classe dépend de la configuration du package et du nombre de classes.
À partir de Spring Framework 5.0, un mécanisme pour résoudre les classes candidates à l'analyse au moment de la compilation sera ajouté comme méthode alternative d'analyse du chemin de classe (dans le but de raccourcir ou de stabiliser le temps de démarrage de l'application).
Note:
Les commentaires de JIRA ne semblent pas le rendre considérablement plus rapide, et cela ne semble pas le rendre plus rapide, il est donc préférable de voir l'effet et de décider d'utiliser ou non l'analyse d'index. Je pense. En outre, dans le cas de test créé pour la vérification des opérations (le nombre total de classes et de classes candidates à l'analyse est d'environ 10 classes), l'analyse du chemin de classe a été légèrement plus rapide. (La différence est d'environ plusieurs dizaines de msec: sweat_smile :)
Pour expliquer brièvement le mécanisme ... En utilisant le "JSR 269: API de traitement d'annotations enfichables" ajouté dans JDK 1.6, "Fichier d'index ( / META-) pour l'acquisition de classes candidates au scan au moment de la compilation INF / spring.components
) »est créé et le fichier est lu lors de l'exécution. (Si vous essayez de faire une image en vain ... cela ressemble à ce qui suit)
Les classes à sortir du fichier d'index au moment de la compilation sont des "annotations composites qui spécifient @ Indexed
et" @ Indexed comme des méta-annotations (telles que
@ Component) "et des annotations qui commencent par
javax. (comme" javax.
". @ Named
et @ ManagedBean
)" "classe d'info-package".
Au moment de l'exécution, la «carte» (index) suivante est générée sur la base du fichier d'index, et la liste de classe des candidats à l'analyse est acquise sans analyser réellement le paquet à analyser pour les composants.
Comme pour l'analyse de chemin de classe, les «classes en dehors du package à analyser», «les classes qui correspondent au filtre d'exclusion» et «les classes qui ne correspondent pas au filtre d'inclusion» ne sont pas enregistrées dans le conteneur DI.
L'activation de l'analyse d'index est facile, ajoutez simplement le module spring-context-indexer
aux artefacts dépendants comme suit:
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
<version>5.0.0.RC1</version>
<optional>true</optional> <!--Il n'est nécessaire que lors de la compilation, donc ne le conditionnez pas dans war, etc.-->
</dependency>
Note:
S'il y a au moins un fichier d'index valide (
/ META-INF / spring.components
) sur le chemin de classe, l'analyse d'index est utilisée par défaut. Par exemple, si votre projet n'utilise passpring-context-indexer
, mais que ses bibliothèques dépendantes (telles que la bibliothèque commune de votre entreprise) contiennent des fichiers d'index, les composants de votre projet ne seront pas analysés. Pour éviter ce phénomène, vous avez deux choix: "Utiliserspring-context-indexer
dans votre propre projet" ou "Ne pas scanner l'index lors de l'exécution". Pour "empêcher l'analyse d'index lors de l'exécution", allez dans "Spring Properties File (spring.properties
directement sous le chemin de la classe) "ou" Java System Properties (option-D
)" à "spring Veuillez spécifier .index.ignore = true
".
@ Nullable
peut être spécifié pour n'importe quel point d'injection: thumbsup:[SPR-15028]: une librairie indépendante ou tierce ([SPR-15028]): lorsque l'injection par câblage automatique est facultative (facultative) Vous pourrez spécifier le @ Nullable
fourni par JSR-305.
Note:
En interne, il juge si le nom de l'annotation est «" Nullable "» ou non, donc il reconnaît également votre propre «@ Nullable».
Par exemple ...
〜4.3
@Component
public class Foo {
private final Bar bar;
private final Baz baz;
public Foo(Bar bar, @Autowired(required = false) Baz baz) {
this.bar = bar;
this.baz = baz;
}
}
Peut également être réécrit dans un style qui n'utilise pas les annotations Spring Framework (exemple: annotation JSR-330 + JSR-305 @ Nullable
) comme indiqué ci-dessous.
pom.xml
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
@Utilisation de Nullable(5.0〜)
import javax.annotation.Nullable;
import javax.inject.Named;
//...
@Named
public class Foo {
private final Bar bar;
private final Baz baz;
public Foo(Bar bar, @Nullable Baz baz) {
this.bar = bar;
this.baz = baz;
}
}
Au fait ... Les annotations JSR-330 (@ Named
et @ Inject
) peuvent également être utilisées dans Spring Framework 4.3. Vous pouvez également utiliser le java.util.Optional
ajouté dans JDK 8 pour indiquer qu'il s'agit d'un point d'injection arbitraire.
Utilisation facultative
import java.util.Optional;
// ...
@Named
public class Foo {
private final Bar bar;
private final Optional<Baz> baz;
public Foo(Bar bar, Optional<Baz> baz) {
this.bar = bar;
this.baz = baz;
}
}
Supplier
): thumbsup:[SPR-14832]: Méthode d'enregistrement du bean (Supplier
) utilisant l'interface fonctionnelle ( Supplier
) pour GenericApplicationContext
et ʻAnnotationConfigApplicationContext Un registerBean
) et une interface pour personnaliser les définitions de bean (BeanDefinitionCustomizer
) sont ajoutés.
Par exemple, si vous procédez comme suit, l'objet renvoyé par le Supplier
spécifié dans l'expression lambda sera géré dans le conteneur DI en tant que bean singleton.
Génération et enregistrement de haricots à l'aide du fournisseur
try (AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext()) {
applicationContext.registerBean(Bar.class);
applicationContext.registerBean(Foo.class, () -> new Foo(applicationContext.getBean(Bar.class))); //★★★ Enregistrement des haricots à l'aide du fournisseur
applicationContext.refresh();
Foo foo = applicationContext.getBean(Foo.class);
// ...
}
De plus ... En utilisant l'interface BeanDefinitionCustomizer
, vous pouvez spécifier les méta-informations (portée, etc.) du bean géré par le conteneur DI. Dans l'exemple ci-dessous, la portée du bean est modifiée en prototype.
java:org.springframework.beans.factory.config.BeanDefinitionCustomizer
@FunctionalInterface
public interface BeanDefinitionCustomizer {
void customize(BeanDefinition bd);
}
Exemple de personnalisation de la définition de bean à l'aide de BeanDefinitionCustomizer
try (AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext()) {
applicationContext.registerBean(Bar.class);
applicationContext.registerBean(Foo.class, () -> new Foo(applicationContext.getBean(Bar.class)),
bd -> bd.setScope(BeanDefinition.SCOPE_PROTOTYPE)); //★★★ Personnalisez les définitions de bean avec BeanDefinitionCustomizer
applicationContext.refresh();
Foo foo = applicationContext.getBean(Foo.class);
Assertions.assertFalse(foo == applicationContext.getBean(Foo.class)); //Étant donné que la portée est un prototype, différentes instances sont renvoyées la première et la deuxième fois
}
Note:
Au fait ... Si vous ne voulez pas utiliser les annotations fournies par Spring (voulez-vous faire du développement basé sur les annotations?), Vous pouvez également utiliser
GenericApplicationContext
.
[SPR-14322 etc.]: Lors de l'application d'AOP à une classe qui implémente une interface en utilisant "Proxy of CGLIB" ( Lorsque proxyTargetClass = true
est spécifié), les annotations spécifiées dans la méthode d'interface (@ Transactional
, @ Cacheable
, @ Sync
, etc.) seront lues.
Par exemple, lorsque vous utilisez la fonction de cache de Spring comme indiqué ci-dessous, annotez l'interface avec le contrôle de cache.
interface
@CacheConfig(cacheNames = "accounts")
public interface AccountService {
@Cacheable
Account getAccount(int id);
}
Classe d'implémentation
public class AccountServiceImpl implements AccountService {
@Override
public Account getAccount(int id) {
return new Account(id);
}
}
La classe de configuration est définie pour utiliser le proxy CGLIB au lieu du proxy JDK lors de l'application de la fonction de mise en cache Spring (lors de la création d'un objet Proxy).
configuration
@EnableCaching(proxyTargetClass = true) //★★★ Configuré pour utiliser le proxy CGLIB
@Configuration
public static class CacheConfiguration {
@Bean
CacheManager cacheManager() {
return new ConcurrentMapCacheManager("accounts");
}
@Bean
AccountService accountService() {
return new AccountServiceImpl();
}
}
Dans cet état, si vous appelez la méthode AccountService obtenue à partir du contexte d'application deux fois avec le même argument, l'objet mis en cache sera renvoyé la deuxième fois.
python
try (AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
CacheConfiguration.class)) {
AccountService service = applicationContext.getBean(AccountService.class);
Account account = service.getAccount(1);
Assertions.assertTrue(account == service.getAccount(1)); //La fonction de cache de Spring est appliquée et l'objet mis en cache est renvoyé la deuxième fois.
}
[SPR-13499]: Gestion de la génération des fichiers xsd spécifiés lors de la définition des beans en XML (fournissant des fichiers xsd pour les versions antérieures) Il sera obsolète et seuls les fichiers xsd de cette version seront stockés dans le fichier JAR. La spécification d'un fichier xsd versionné dans un fichier XML est toujours prise en charge, mais le même fichier xsd est toujours utilisé lors de l'analyse d'un fichier XML.
Sur Spring Framework 4.3, il était possible d'utiliser les attributs pris en charge dans les versions précédentes comme suit.
Fichier XML de définition de bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> <!-- ★★★ 3.Spécifiez le fichier XSD pour 2-->
<bean class="com.example.di.Foo">
<property name="bar">
<ref local="bar"/> <!-- ★★★ 3.x a un attribut local-->
</property>
</bean>
<bean id="bar" class="com.example.di.Bar"/>
</beans>
Si vous utilisez ce fichier avec Spring Framework 5.0 ... Lors de l'analyse d'un fichier XML, une violation de schéma se produit et l'erreur suivante se produit.
org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 9 in XML document from class path resource [com/example/di/applicationContext.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 9; columnNumber: 25; cvc-complex-type.3.2.2:élément'ref'Attribuer à'local'Ne peut pas être inclus.
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:399)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336)
Pour utiliser ce fichier sur Spring Framework 5.0, il est nécessaire de prendre des mesures telles que "modifier l'attribut" bean "au lieu de l'attribut" local "ou" utiliser "l'attribut ref de l'élément" local
de l'élément <ref>
"est un exemple d'attribut qui ne peut pas être utilisé, et plusieurs autres ne peuvent pas être utilisés.
Exemple de changement d'attribut bean
<bean class="com.example.di.Foo">
<property name="bar">
<ref bean="bar"/>
</property>
</bean>
<property>Exemple d'utilisation de l'attribut ref de l'élément
<bean class="com.example.di.Foo">
<property name="bar" ref="bar"/>
</bean>
De plus, il est inutile de spécifier la version lors de la spécification du fichier XSD (assez déroutant), il est donc recommandé de changer pour spécifier le fichier XSD qui n'inclut pas la version à cette occasion.
Exemple de spécification d'un fichier XSD non versionné
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--★★★ Passer au fichier non versionné-->
<!-- ... -->
</beans>
Cette fois, nous avons présenté les principaux changements liés aux conteneurs DI. Peut-être que "la prise en charge de l'analyse d'index" est le principal changement, mais il ne semble pas démarrer beaucoup plus rapidement, alors attendez-vous à de futures améliorations! !! Est-ce quelque chose comme: wink: La prochaine fois, je présenterai "Changements majeurs liés à WebMVC".
Recommended Posts