编程知识 cdmana.com

Spring

Un..SpringPremière connaissance

1.SpringQu'est - ce que c'est??

1.1 SpringC'est un cadre open source

1.2 SpringConçu pour simplifier le développement d'applications au niveau de l'entreprise,UtiliserSpringPeut rendre simpleJavaBeanAvant la mise en œuvre, il n'y avait queEJBFonctions à réaliser

1.3 SpringC'est un**IOCContrôle inverse(DIInjection dépendante)EtAOPProgrammation orientée tangente**Cadre du conteneur

2.Description détailléeSpring

2.1 Léger:Ça ne veut pas direSpringDejarLa taille du sac,C'est juste que...SpringC'est non intrusif(Prêt à l'emploiSpringHeure,Il n'y a pas besoin deSpringPour toute interface fournie,Pas besoin d'hériter de ses parents,Profitez de ses fonctions)Basé surSpringLes objets d'une application développée peuvent être indépendants deSpringDeAPI

2.2 Injection dépendante(DI—dependency injection、IOC)

2.3 Programmation orientée tangente(AOP—aspect oriented programming)

2.4 Conteneur:SpringC'est un conteneur.,Parce qu'il contient et gère le cycle de vie de l'objet d'application

2.5 Cadre:SpringMise en œuvre de l'utilisation de configurations de composants simples combinées en une application complexe.InSpringPeut être utilisé dansXMLEtJavaAnnotation combine ces objets.

2.6 Guichet unique:InIOCEtAOP Basé sur un cadre open source qui intègre toutes sortes d'applications d'entreprise (Par exemple:Struts2、Hibernate、Mybatis) Et une excellente bibliothèque de tiers (En fait,Spring.Il fournit également une couche de présentationSpring MVCEt persistantSpring JDBC)

3.Spring Module

Insérer la description de l'image ici

Core ContainerConteneur Central

AOP AspectsProgrammation orientée tangente

InstrumentationIntégration

MessagingMessage

Test Tests

4.Construction Spring Environnement de développement

4.1 Modifierpom.xmlDocumentation,Introduction de dépendances connexes

<!-- IntroductionspringDépendance-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.4</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.3.4</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.3.4</version>
</dependency>

4.2 NouveauSpring Profil pour

Un classique Spring Le projet nécessite la création d'un ou de plusieurs Bean Profil, Ces profils sont utilisés dans Spring IOC Configuration dans le conteneur Bean.

Bean Le fichier de configuration peut être placé dans classpathEn bas.:

NouveauresourcesDossiers

Insérer la description de l'image ici

Oui.resources Le dossier est défini à Resources Root

Insérer la description de l'image ici

NouveauspringProfil de base pour, Généralement nommé par défaut applicationContext.xml

5.Création HelloWorld.java

package com.cm.spring.ch01;


import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/** IOCContrôle de l'inversion:  Créer des objets par soi - même ,On peut passer.Spring Conteneur pour créer des objets , On en tire des objets  */

public class HelloWorld {
    

	private String userName;

	public void setUserName1(String username){
    

		System.out.println("setUserName1:"+username);

		this.userName =  username;

	}

	public HelloWorld(){
    

		System.out.println("Méthode de construction...");

	}

 	public void hello(){
    

		System.out.println("Hello: "+userName);

	}

}


6.ConfigurationapplicationContext.xml

In xml Dans le document bean Noeuds pour configurer beanExemple

6.1 Parmi euxid- Oui.Bean Nom de

1).In IOC Doit être unique dans le contenant

2).Si id Non spécifié,Spring Le nom complet de la classe est automatiquement utilisé comme Bean Le nom de

3).id Plusieurs noms peuvent être spécifiés , Une virgule peut être utilisée entre les noms 、Point - virgule、Ou espace séparé

6.2 Injection d’attributs

1).L'injection d'attributs passe setter Injection de la méthodeBean Valeur de la propriété ou objet dépendant de

2). Utilisation de l’injection d’attributs Élément, Utiliser name Attribution des attributs Bean Nom de la propriété pour,value Propriété ou Le noeud enfant spécifie la valeur de l'attribut

<?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">

	<!-- Configurationbean -->

	<!-- classValeur de l'attribut: Le nom complet de la classe est par réflexion ,ParSpringCrééHelloWorldObjet de id Utilisé pour identifier l'objet créé  nameCe qui correspondsetXxx()Dansxxx value Est l'attribution d'une valeur à un attribut dans une classe  -->

	<bean id="helloWorld" class="com.etc.spring.ch01.HelloWorld">

		<property name="userName1" value="Spring"></property>

	</bean>

</beans>

7.Tests

ApplicationContext Principales classes de mise en œuvre:ClassPathXmlApplicationContext: Charger le fichier de configuration à partir du chemin de classe

public class MainTest{
    
  
  public static void main(String[] args) {
    

		//1.CréationHelloWorldUn objet de

		//HelloWorld h = new HelloWorld();

		//2.PouruserNameAttribution des attributs

		//h.setUserName("zhangsan");

		//h.hello();



		//1.CréationSpringDeIOCObjet conteneur

		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

		//2.DeIOCObtenir dans le conteneurBeanExemple

		HelloWorld h = (HelloWorld)ctx.getBean("helloWorld");

		System.out.println(h);

		//3.Méthode d'appel

		h.hello();

	}
  
}

2..SpringDeIOC

2.1、Spring_IOC&DIGénéralités

1.IOCEtDIGénéralités

IOC(Inversion of Control):L'idée est d'inverser la direction de l'acquisition des ressources. Les méthodes traditionnelles de recherche de ressources exigent que le composant lance une demande de recherche de ressources au conteneur. En réponse, Ressources de retour en temps opportun du conteneur. Et appliqué IOC Après, C'est le conteneur qui pousse activement les ressources vers les composants qu'il gère , Tout ce qu'un composant a à faire est de choisir une façon appropriée d'accepter les ressources . Ce comportement est aussi connu sous le nom de forme passive de recherche .

DI(Dependency Injection) — IOC Une autre façon d'exprimer:C'est - à - dire que les composants sont prédéfinis d'une manière ou d'une autre(Par exemple: setter Méthodes) Accepter l'injection de ressources d'un conteneur comme . Par rapport à IOC En termes,C'est plus direct.

2.IOC Développement de la pensée

IOC Prébiotique – Séparation des interfaces et mise en œuvre : La façon la plus couplée , Parce que vous devez connaître les détails de l'interface et de chacune de ses classes d'implémentation dans la classe de service de rapport

Besoins: Générer HTML Ou PDF Différents types de rapports dans le format .

IOC Prébiotique – Adopter le modèle de conception de l'usine

IOC – Avec contrôle inverse

2.2、IOC Conteneur BeanFactory & ApplicationContext Généralités

1.BeanFactory

1.In Spring IOC Lecture du conteneur Bean Création de configuration Bean Avant l'Instance, Il doit être instantané . Seulement après l'Instanciation du conteneur , C'est à partir de IOC Obtenir dans un contenant Bean Exemple et utilisation.

2.Spring Deux types de IOC Mise en œuvre du conteneur.

1).BeanFactory: IOC Mise en œuvre de base du conteneur.

2).ApplicationContext: Offre plus de fonctionnalités avancées . - Oui. BeanFactory Sous - interface pour.

3).BeanFactory - Oui. Spring Infrastructure du cadre,Orientation Spring En soi;ApplicationContext Orienté vers l'utilisation Spring Le développeur du cadre,Presque toutes les applications sont utilisées directement ApplicationContext Au lieu du sous - sol BeanFactory

4). Quelle que soit la méthode utilisée , Identique au profil .

2.ApplicationContext

1.ApplicationContext Principales classes de mise en œuvre:

ClassPathXmlApplicationContext:Sous le chemin de classe(binSous la table des matières)Charger le profil

FileSystemXmlApplicationContext: Charger le fichier de configuration à partir du système de fichiers

2.ConfigurableApplicationContext Extension à ApplicationContext, Ajout de deux nouvelles méthodes principales :refresh() Et close(), Jean ApplicationContext Avec démarrage、 Possibilité de rafraîchir et de fermer le contexte

3.ApplicationContext Instancie tous les singletons lors de l'initialisation du contexte Bean.

4.WebApplicationContext Est spécialement conçu pour WEB Préparé pour application ,Il permet de WEB Initialisation complète dans le chemin du Répertoire racine

2.3、Mode de dépendance à l’injection

1.Injection d’attributs

1).L'injection d'attributs passe setter Injection de la méthodeBean Valeur de la propriété ou objet dépendant de

2). Utilisation de l’injection d’attributs Élément, Utiliser name Attribution des attributs Bean Nom de la propriété pour,value Propriété ou Le noeud enfant spécifie la valeur de l'attribut

3). L'injection d'attributs est la méthode d'injection la plus couramment utilisée dans les applications pratiques

<!-- nameCe qui correspondsetXxx()Dansxxx value Est l'attribution d'une valeur à un attribut dans une classe -->
<bean id="helloWorld" class="com.etc.spring.ch01.HelloWorld">
    <property name="userName1" value="Spring"></property>
</bean>

2.Méthode de construction injection

1).Injection par constructionBean Valeur de la propriété ou objet dépendant de ,C'est promis. Bean L'instance peut être utilisée après l'Instanciation .

2). Le constructeur injecte Attributs déclarés dans l'élément , Il n'y a pas de name Propriétés

3).

Appuyez.Index Faire correspondre les paramètres entrants :

Appuyez.Type Faire correspondre les paramètres entrants :

2.4、 Détails de la configuration des attributs

1.Valeur nominale

Valeur nominale: Valeurs représentées par des chaînes disponibles ,Peut passer Étiquette de l'élément ou value Propriété pour l'injection.

Types de données de base et leurs classes d'encapsulation、String Des types comme celui - ci peuvent être injectés de façon littérale .

Si la valeur nominale contient des caractères spéciaux ,Peut être utilisé ==<![CDATA[]]> == Envelopper les lettres .

2.Citer d'autres Bean

1). Composition de la demande Bean Souvent, vous devez travailler ensemble pour compléter la fonctionnalité de votre application . Pour faire Bean Accès mutuel , Doit être Bean Spécifier la paire dans le fichier de configuration Bean Références.

2). In Bean Dans le profil de, Peut passer Élément ou refLa propriété est Bean La propriété ou le paramètre constructeur de spécifie la paire Bean Références.

3). Peut également être inclus dans l'attribut ou le constructeur Bean Déclaration, Comme ça. Bean Appelé interne Bean.

  > Quand Bean  Lorsque l'instance n'est utilisée que pour un attribut particulier ,  Il peut être déclaré interne  Bean. Interne Bean  Déclaration directement contenue dans  <property> Ou <constructor-arg> Dans les éléments,  Aucun réglage n'est nécessaire  id Ou name Propriétés
  > Interne Bean  Ne pas utiliser ailleurs 

3.Propriétés en cascade

<?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">

    <bean id="p" class="com.cm.ch02.ref.Person">
        <property name="username" value="Li - si."></property>
        <property name="age" value="35"></property>
        <property name="car" ref="c"></property>
        <!--  Modification du prix du véhicule par une opération de propriété en cascade  1.Équivalent àPersonObjet appelésetCar(),carObjet appelésetPrice() 2. La propriété doit d'abord initialiser l'affectation ,Sinon, une exception se produit -->
        <property name="car.price" value="500000"></property>
    </bean>

    <bean id="c" class="com.cm.ch02.ref.Car">
        <property name="label" value="aodi"></property>
        <property name="price" value="300000"></property>
    </bean>

</beans>

4.Propriétés de la collection

1.In Spring Vous pouvez utiliser un ensemble intégré de xml Étiquettes(Par exemple: , Ou ) Pour configurer les propriétés de la collection .

2.Configuration java.util.List Propriétés du type, Doit être spécifié Étiquettes, Inclure des éléments dans l'étiquette . Ces étiquettes peuvent être Spécifiez une valeur constante simple , Adoption Préciser pour les autres Bean Références. Adoption Spécifiez intégré Bean Définition. Adoption Spécifier un élément vide .

3.Définition et List C'est pareil, Utilisez tous

4.Configuration java.util.Set À utiliser Étiquettes, La méthode de définition de l'élément est comparée à List C'est pareil.

5.Java.util.Map Adoption Définition de l'étiquette, Vous pouvez utiliser plusieurs Comme sous - étiquette. Chaque entrée contient une clé et une valeur .

6.Il doit être Définir la clé dans l'étiquette

7. Parce que les types de clés et de valeurs ne sont pas limités , Il est donc libre de leur assigner , , Ou Élément.

8.Vous pouvez Map Clé et valeur pour Définition des attributs pour: Utilisation constante simple key Et value Pour définir; Bean Par référence key-ref Et value-ref Définition des attributs

9.Utiliser utility scheme Définir la collection

1). Lors de la définition d'une collection à l'aide d'une étiquette de collection de base , La collection ne peut pas être considérée comme indépendante Bean Définition, Autres causes Bean Impossible de faire référence à la collection , Donc ça ne peut pas être différent Bean Partage des collections entre .

2).Peut être utilisé util schema L'étiquette set dans définit une collection séparée Bean. Il est important de noter que, Il doit être Ajouter à l'élément racine util schema Définition

5.pEspace de noms

1.Pour simplifier XML Configuration du fichier,De plus en plus XML Le fichier utilise des attributs plutôt que des informations de configuration d'éléments enfants .

2.Spring De 2.5 La version commence à introduire un nouveau p Espace de noms,Peut passer Configuration des propriétés de l'élément Bean Propriétés de.

3.Utiliser p Après l'espace de noms,Basé sur XML La configuration sera encore simplifiée

2.5、BeanLa portée de

1.In Spring Moyenne, Ça pourrait être dans Élément scope Paramètres dans la propriété Bean La portée de.

2.Par défaut, Spring Juste pour chaque IOC Déclaré dans le conteneur Bean Créer une instance unique , Tout IOC Cette instance peut être partagée à l'échelle du conteneur :Tous les getBean() Appel et Bean Toutes les références renvoient cette seule Bean Exemple. Ce champ d'application est appelé singleton, C'est tout. Bean Champ d'application par défaut pour .

2.6、Fichiers de propriétés externes

1. Nouveau sous classpath db.propertiesFichiers de propriétés

#mysql
db.name=root
db.password=12345678
db.jdbcUrl=jdbc:mysql://localhost:3306/dborder?useUnicode=true&characterEncoding=utf-8
db.driverClass=com.mysql.jdbc.Driver

2.Modifierpom.xmlDocumentation

<!--mysqlDrive Pack -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>

<!--c3p0 -->
<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>

Attention!: Selon l'installation actuelle mysqlVersion,Choisir le bonmysql Numéro de version du lecteur

3.NouveauspringProfil de base pour

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--  Importer un fichier de propriétés externes  -->
    <context:property-placeholder location="classpath:db.properties" />

    <!-- Configurationc3p0Pool de connexion de données -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--  Utilisez le key -->
        <property name="user" value="${db.name}"></property>
        <property name="password" value="${db.password}"></property>
        <property name="jdbcUrl" value="${db.jdbcUrl}"></property>
        <property name="driverClass" value="${db.driverClass}"></property>
    </bean>

</beans>

4.Tests

package com.cm.ch03.properties;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class MainTest {
    

    public static void main(String[] args) throws SQLException {
    

        ApplicationContext ac = new ClassPathXmlApplicationContext("beans_properties.xml");
        ComboPooledDataSource pool = (ComboPooledDataSource)ac.getBean("dataSource");
        System.out.println(pool);
        Connection connection = pool.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement("select * name from t_user where id=?");
        preparedStatement.setInt(1, 1);
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()){
    
            System.out.println(resultSet.getString(1));
        }
        connection.close();
        pool.close();
    }

}

2.7、GestionBeanLe cycle de vie de

1.Spring IOC Paire de conteneurs Bean Le processus de gestion du cycle de vie

1).Créé par un constructeur ou une méthode d'usine Bean Exemple

2).Pour Bean Pour définir les valeurs des propriétés et pour d'autres Bean Références

3).Appelez Bean Méthode d'initialisation pour

4).Bean Prêt à l'emploi

5). Quand le conteneur est fermé closeHeure, Appelez Bean Méthodes de destruction

In Bean Défini dans la Déclaration de init-method Et destroy-method Propriétés, Pour Bean Spécifiez les méthodes d'initialisation et de destruction.

2.Création Bean Post - processeur

1.Bean Le post - processeur permet des paires avant et après l'appel à la méthode d'initialisation Bean Traitement supplémentaire.

2.Bean Paire de post - processeurs IOC Tout dans le conteneur Bean Exemple par exemple, Au lieu d'une seule instance . Son application typique est: Vérifiez Bean L'exactitude des attributs ou leur modification selon des critères précis Bean Propriétés de.

3.C'est exact.Bean Pour le post - processeur , Doit être réalisé**BeanPostProcessorInterface**. Avant et après l'appel de la méthode d'initialisation , Spring Va mettre chaque Bean Les exemples sont transmis aux deux méthodes suivantes pour chacune des interfaces ci - dessus: :

3.Ajouter Bean Après le post - processeur Bean Le cycle de vie de

1).Créé par un constructeur ou une méthode d'usine Bean Exemple

2).Pour Bean Pour définir les valeurs des propriétés et pour d'autres Bean Références

3).Oui. Bean Instance passée à BeanPost - processeurpostProcessBeforeInitialization Méthodes

4).Appelez Bean Méthode d'initialisation pour

5).Oui. Bean Instance passée à Bean Post - processeur postProcessAfterInitializationMéthodes

6).Bean Prêt à l'emploi

7).Quand le conteneur est fermé, Appelez Bean Méthodes de destruction

2.8、Bean Comment configurer

1. Par nom de classe complet

2.Par la méthode de l'usine(Méthode statique de l'usine & Exemple de méthode d'usine)

2.1 Créer en appelant la méthode statique Factory Bean

1.Appeler la méthode statique Factory pour créer Bean Est d'encapsuler le processus de création d'objets dans une méthode statique . Lorsque le client a besoin d'un objet , Il suffit d'appeler la méthode statique , Sans se soucier des détails de la création de l'objet .

2. Pour déclarer ce qui a été créé par une méthode statique Bean, Besoin de Bean De class La classe dans la propriété qui spécifie la méthode qui possède l'usine , En même temps factory-method Nom de la méthode d'usine spécifiée dans la propriété . Enfin, Utiliser L'élément passe les paramètres de la méthode pour la méthode .

StaticCarFactoryCatégorie

beans-factory.xml

2.2 Créer en appelant la méthode instance Factory Bean

1.Exemple de méthode d'usine: Méthode d'encapsulation du processus de création d'un objet dans une autre instance d'objet . Lorsque le client a besoin de demander un objet , Il suffit d'appeler cette méthode d'instance sans se soucier des détails de création de l'objet .

2. Pour déclarer ce qui a été créé par la méthode instance Factory Bean

1).In bean De factory-bean La propriété spécifie la propriété qui possède la méthode Factory Bean

2).In factory-method Nom de la méthode d'usine spécifiée dans la propriété

3).Utiliser construtor-arg L'élément passe les paramètres de la méthode pour la méthode Factory

InstanceCarFactoryCatégorie

beans-factory.xml

3.AdoptionFactoryBeanDe la façon dont

1.Spring Il existe deux types de Bean, L'un est communBean, L'autre est l'usineBean, C'est - à - dire:FactoryBean.

2.Usine Bean Comme d'habitude.BeanC'est différent., L'objet retourné n'est pas une instance de la classe spécifiée, Il retourne à l'usine Bean De getObject Objet retourné par la méthode

2.9、Spring IOC Notes+XMLÉdition

Configuration basée sur des annotationsBean: Identifier l'utilisation de l'annotation beanConfigurer pourIOCDans le récipient

Assemblage basé sur des annotations BeanPropriétés de:JeanbeanAvecbean Il y a une association entre

1.Scan des composants(component scanning)

Spring Capable de classpath Balayage automatique inférieur , Détecter et instancier les composants avec des annotations spécifiques .

2. Les composants spécifiques comprennent:

Configuration basée sur des annotationsBean

@Component: Notes de base, Marqué d'un Spring Éléments gérés

@Repository: Identifier la couche persistante daoAssemblage des couches

@Service: Identifier le niveau de service (Business level)Components

@Controller: Identifier les composants de la couche de présentation

Assemblage basé sur des annotations BeanPropriétés de

@Value(""):Assigner une valeur à la propriété, Injecter des propriétés de type simple @Value(value=“abc”)private String name;

@Autowired:Réaliser l'assemblage automatique

3. Pour les composants scannés , Spring Il y a une politique de nommage par défaut

Utiliser un nom de classe non qualifié , Première lettre minuscule; Peut également être utilisé dans les notes passant par value La valeur de l'attribut identifie le nom du composant .

value Est la propriété par défaut ,Pour quevalueOmettre ne pas écrire;Peut être utilisévalue Valeur de l'attribut à identifier beanInIOCDans le conteneurid.

4.Spécifier le paquet de numérisation

Après avoir utilisé une annotation spécifique sur une classe de composants , Il faut aussi Spring Déclaré dans le profil de <context:component-scan> Indique les paquets à numériser :

1).base-package La propriété spécifie un paquet de classe de base à numériser,Spring Le conteneur scannera toutes les classes de ce paquet de classe de base et de ses sous - paquets .

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DésignationSpring IOC Paquets scannés par conteneur  -->
    <context:component-scan base-package="com.cm.ch04"></context:component-scan>

</beans> 

2). Quand il faut scanner plusieurs paquets , Vous pouvez utiliser des virgules pour séparer.

<!-- DésignationSpring IOC Paquets scannés par conteneur , Lorsqu'il y a plus d'un paquet , Vous pouvez utiliser des virgules pour séparer  -->
<context:component-scan base-package="com.cm.ch04 , com.cm.ch02"></context:component-scan>

3). Si vous ne voulez numériser que des classes spécifiques et non toutes les classes sous le paquet de base ,Disponible en resource-pattern Propriétés filtrant des classes spécifiques.

<!-- DésignationSpring IOC Paquets scannés par conteneur ,Adoptionresource-pattern Spécifier les ressources numérisées  -->
<context:component-scan base-package="com.cm.ch04" resource-pattern="entity/*"></context:component-scan>

4).<context:include-filter> Le noeud enfant représente la classe cible à inclure

<context:exclude-filter> Les noeuds enfants représentent les classes cibles à exclure

<context:component-scan>Vous pouvez en avoir plusieurs<context:include-filter> Et <context:exclude-filter> Sous - noeud.

<context:include-filter>Et<context:exclude-filter> Les noeuds enfants supportent plusieurs types d'expressions de filtre :

5.Réalisation de l'injection d'attributs basée sur l'annotation

(1)@Autowired:Montage automatique par type d'attribut

Première étape Prends ça. service Et dao Création d'objets,In service Et dao Classe ajouter des annotations d'objets de création séparément @ServiceEt@Repository

Deuxième étape In service Injection dao Objet,In service Ajout de classe dao Propriétés de type,Utiliser des annotations sur les propriétés

(2)@Qualifier:Injection par nom

C'est@Qualifier Utilisation des annotations,Et en haut@Autowired À utiliser ensemble

(3)@Resource:Peut être injecté par type,Peut être injecté par nom

3.5、Spring IOC Configurer la classe+Version annotée

Trois.SpringDeAOP

3.1、AOP Principes

1.Besoins

Augmentation de la demande:

Besoins1-Log: Suivre les activités en cours pendant l'exécution du programme

Besoins2-Validation: On s'attend à ce que la calculatrice ne traite que les opérations avec des nombres positifs

2. Fragment de mise en œuvre du Code

ICount Interface calculatrice

package com.cm.ch05.aop;

public interface ICount {
    
	
	public int add(int i, int j);
	
	public int sub(int i, int j);
	
	public int mul(int i, int j);
	
	public int div(int i, int j);
}


CountImpl Classe d'implémentation de calculatrice

package com.cm.ch05.aop;

import org.springframework.stereotype.Component;

@Component
public class CountImpl implements ICount{
    

	@Override
	public int add(int i, int j){
    
		System.out.println("add()");
		int result = i+j;
		return result;
	}

	@Override
	public int sub(int i, int j) {
    
		System.out.println("sub()");
		int result = i-j;
		return result;
	}

	@Override
	public int mul(int i, int j) {
    
		System.out.println("mul()");
		int result = i*j;
		return result;
	}

	@Override
	public int div(int i, int j) {
    
		System.out.println("div()");
		int result = i/j;
		return result;
	}

} 

CountLogImpl Classe d'implémentation du Journal de calcul

package com.cm.ch05.aop;

//Ajouter une exigence:Suivi des journaux
public class CountLogImpl implements ICount{
    

	@Override
	public int add(int i, int j) {
    
		System.out.println("Suivi des journaux:the method add begin with [ "+i+","+j+" ]");
		int result = i+j;
		System.out.println("Suivi des journaux:the method add end with "+result);
		return result;
	}

	@Override
	public int sub(int i, int j) {
    
		System.out.println("Suivi des journaux:the method sub begin with [ "+i+","+j+" ]");
		int result = i-j;
		System.out.println("Suivi des journaux:the method sub end with "+result);
		return result;
	}

	@Override
	public int mul(int i, int j) {
    
		System.out.println("Suivi des journaux:the method mul begin with [ "+i+","+j+" ]");
		int result = i*j;
		System.out.println("Suivi des journaux:the method mul end with "+result);
		return result;
	}

	@Override
	public int div(int i, int j) {
    
		System.out.println("Suivi des journaux:the method div begin with [ "+i+","+j+" ]");
		int result = i/j;
		System.out.println("Suivi des journaux:the method div end with "+result);
		return result;
	}

}

Questions:

1.Code confus:Augmentation des besoins non opérationnels(Journal et vérification, etc.)Après l'adhésion, L'ancienne méthode d'affaires s'est considérablement développée. Chaque approche doit tenir compte de plusieurs autres préoccupations tout en traitant de la logique de base..

2.Dispersion des codes: Prenons l'exemple des exigences en matière de registres., Juste pour répondre à ce besoin unique, Doit être dans plusieurs modules(Méthodes)Répéter le même Code de log plusieurs fois. Si les exigences en matière de journalisation changent, Tous les modules doivent être modifiés.

3. Résoudre les problèmes ci - dessus en utilisant des agents dynamiques

Principes du modèle de conception des agents: Envelopper l'objet avec un agent, L'objet proxy remplace ensuite l'objet original. Tout appel à l'objet original passe par un proxy. L'objet proxy détermine si et quand l'appel de méthode est transféré à l'objet original.

ArithmeticCalculatorLogProxyClasse de proxy dynamique

public class ArithmeticCalculatorLogProxy {
       // ArithmeticCalculatorLogProxyClasse de proxy dynamique
    //Objet à représenter
    private ArithmeticCalculator target;
    public ArithmeticCalculatorLogProxy(ArithmeticCalculator target){
    
        this.target = target;
    }
    public ArithmeticCalculator getLogProxy(){
    
        ArithmeticCalculator proxy = null;
        // Quel chargeur de classe est responsable du chargement de l'objet mandataire 
        ClassLoader loader = target.getClass().getClassLoader();
        //Type d'objet mandataire
        Class[] interfaces = new Class[]{
    ArithmeticCalculator.class};
        // Lorsque vous appelez une méthode dans un objet mandataire , Code à exécuter 
        InvocationHandler h = new InvocationHandler() {
    
            /** * proxy: L'objet proxy retourné .En général, dansinvoke L'objet n'est pas utilisé dans la méthode  * method: Méthode appelée  * args:Quand la méthode est appelée,Paramètres entrants */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
                String methodName = method.getName();
                //Log
                System.out.println("the method "+methodName+" begin with "+Arrays.asList(args));
                //Méthode d'exécution
                Object result = method.invoke(target, args);
                //Log
                System.out.println("the method "+methodName+" end with "+result);
                return result;
            }
        };
        proxy = (ArithmeticCalculator)Proxy.newProxyInstance(loader, interfaces, h);
        return proxy;
    }
}


Tests

ArithmeticCalculator target = new ArithmeticCalculatorImpl();
ArithmeticCalculator proxy = new ArithmeticCalculatorLogProxy(target).getLogProxy();
		
int result = proxy.add(1, 2);
System.out.println("-->"+result);

result = proxy.div(4, 2);
System.out.println("-->"+result);

3.2、AOP Introduction

1.AOP(Aspect-Oriented Programming, Programmation orientée tangente)

C'est une nouvelle méthodologie , C'est une tradition OOP(Object-Oriented Programming, Programmation orientée objet) Pour compléter.

AOP Les principaux objets de programmation de Tangente(aspect), Et le plan tangent Préoccupations transversales modulaires .

En application AOP Programmation,La fonction publique doit encore être définie, Mais il est possible de définir clairement où se trouve cette fonction , Comment appliquer, Et il n'est pas nécessaire de modifier les classes touchées. De cette façon, les préoccupations transversales sont modularisées en objets spéciaux (Tangente)- Oui..

2.AOPAvantages

1). Chaque chose est logique dans une position , Le Code n'est pas dispersé , Facile à entretenir et à mettre à jour

2). Module d'affaires plus concis , Contient uniquement le Code d'entreprise de base .

3.AOPTerminologie

1). Tangente(Aspect): Préoccupations transversales(Fonctionnalité couvrant plusieurs modules de l'application) Classes modulaires

2). Notification(Advice): Le travail que la section doit accomplir( Chaque méthode de la section est appelée notification )

3). Objectifs(Target): Objet notifié

4). Agents(Proxy): Objet créé après application de la notification à l'objet cible

5). Point de connexion(Joinpoint):Un endroit précis où le programme est exécuté( Une présence physique spécifique ): Comme avant qu'une méthode de la classe ne soit appelée 、Après appel、La méthode lance une exception, etc..Le point de connexion est déterminé par deux informations: Point d'exécution du programme représenté par la méthode ; L'orientation indiquée par le point relatif .Par exemple ArithmethicCalculator#add() Point de connexion avant l'exécution de la méthode , Le point d'exécution est ArithmethicCalculator#add(); L'orientation est la position avant l'exécution de la méthode

6). Tangente(pointcut): Chaque classe a plusieurs points de connexion :Par exemple ArithmethicCalculator Toutes les méthodes sont en fait des points de connexion , C'est - à - dire que le point de connexion est une transaction qui existe objectivement dans une classe de programme .AOP Localiser un point de connexion spécifique par un point tangent .Analogies:Le point de connexion correspond à un enregistrement dans la base de données, Le point tangent correspond aux critères de requête .Les tangentes et les points de connexion ne sont pas une relation individuelle, Une tangente correspond à plusieurs points de connexion , La tangente passe org.springframework.aop.Pointcut Description de l'interface , Il utilise des classes et des méthodes comme critères de requête pour les points de connexion .

3.3、Spring AOP Notes+XMLÉdition

1).AspectJ:Java Le plus complet et le plus populaire de la communauté AOP Cadre.

2).In Spring2.0 Dans la version précédente, Vous pouvez utiliser AspectJ Annotation ou basée sur XML Configuré AOP

1.In Spring Activer AspectJ Support d'annotation,Modifierpom.xml

<!-- IntroductionspringDeAOPDépendance -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>5.2.6.RELEASE</version>
</dependency>

<!-- IntroductionaspectjDépendance -->
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.4</version>
</dependency>

2.NouveauspringProfil de base pour

Oui. Spring IOC Activer dans le conteneur AspectJ Support d'annotation, Tant que Bean Un vide est défini dans le fichier de configuration XML Élément aop:aspectj-autoproxy.Quand Spring IOC Conteneur détecté Bean Dans le profil aop:aspectj-autoproxy Quand l'élément, Sera automatiquement AspectJ Tangentielle Bean Créer un agent.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">


    <!-- Prise en charge de la configuration des annotations -->
    <context:component-scan base-package="com.cm.ch05.aop" />

    <!-- SoutienAOPCadre -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

3.Avec AspectJ Annotation déclaration tangente

1).Oui. Spring Déclaration du milieu AspectJ Tangente, C'est tout.In IOC Dans le récipient Déclarer la tangente comme Bean Exemple. Quand Spring IOC Initialisation dans le conteneur AspectJ Après la coupe, Spring IOC Les contenants seront pour ceux qui AspectJ Les faces coupées correspondent Bean Créer un agent.

2).In AspectJ Dans les notes, La section n'est qu'une Avec @Aspect NotesDe Java Catégorie.

3).Une notification est une simple annotation avec une sorte d'annotation Java Méthodes.

4).AspectJ Soutien 5 Types de notes de notification:

@Before: Pré - notification, Exécuter avant l'exécution de la méthode

@After: Post - notification, Exécuter après l'exécution de la méthode

@AfterReturning: Retour à la notification, Exécuter après que la méthode a retourné les résultats

@AfterThrowing: Avis d'exception, Après que la méthode a lancé une exception

@Around: Notification surround, Exécuter autour de la méthode

4.Notification

1).Pré - notification

Notification effectuée avant l'exécution de la méthode , Utilisation des notifications préalables @Before Notes, Et prendre la valeur de l'expression pointcut comme valeur d'annotation .

2).Post - notification

@After Est exécuté après la fin du point de connexion , C'est - à - dire lorsque le point de connexion renvoie un résultat ou lance une exception , L'avis suivant indique la fin de la méthode .

3).Retour à la notification

Que le point de connexion retourne normalement ou lance une exception , Les postnotifications sont effectuées . Si vous ne voulez enregistrer que lorsque le point de connexion est retourné , La notification de retour doit être utilisée au lieu de la notification post érieure .

Accéder à la valeur de retour du point de connexion dans la notification de retour

1).Dans l'avis de retour, Tant que returning Propriétés ajoutées à @AfterReturning NotesMoyenne, La valeur de retour du point de connexion est accessible. La valeur de cette propriété est le nom du paramètre utilisé pour passer la valeur de retour.

2). Vous devez ajouter un paramètre du même nom à la signature de la méthode de notification . Au moment de l'exécution, Spring AOP La valeur de retour est passée par ce paramètre.

3).L'expression tangente originale doit apparaître dans pointcut Dans les propriétés

4).Avis d'exception

1). Les notifications d'exception ne sont effectuées que si une exception est lancée au point de connexion

2).Oui. throwing Propriétés ajoutées à @AfterThrowing NotesMoyenne, Vous pouvez également accéder aux exceptions lancées par les points de connexion. Throwable Est une superclasse de toutes les classes d'erreurs et d'exceptions . Ainsi, dans la méthode de notification des exceptions, vous pouvez saisir toutes les erreurs et exceptions.

3).Si vous n'êtes intéressé que par un type particulier d'exception, Les paramètres peuvent être déclarés comme des types de paramètres pour d'autres exceptions. La notification n'est alors exécutée que lorsqu'une exception de ce type et de ses sous - classes est lancée.

5).Notification surround

1). Notification surround**@Around** Est le plus puissant de tous les types de notification , Capable de contrôler complètement les points de connexion. Vous pouvez même contrôler si les points de connexion sont exécutés.

2).Pour les notifications surround, Le type de paramètre du point de connexion doit être ProceedingJoinPoint . C'est... JoinPoint Sous - interface pour, Permet de contrôler quand, Si le point de connexion est exécuté.

3).Un appel explicite est nécessaire dans la notification surround ProceedingJoinPoint De proceed() Méthodes Pour exécuter la méthode représentée . Si vous oubliez de le faire, la notification sera exécutée, Mais la méthode cible n'a pas été appliquée.

4).Attention!: La méthode qui entoure la notification doit renvoyer les résultats après l'exécution de la méthode cible, C'est - à - dire appeler joinPoint.proceed(); Valeur de retour de, Sinon, une exception de pointeur vide se produira

5. Écrit avec la signature de la méthode AspectJ Expression pointcut

1).execution * com.etc.spring.ArithmeticCalculator.*(…): Ça correspond ArithmeticCalculator Toutes les méthodes déclarées dans ,Le premier * Représente n'importe quel modificateur et n'importe quelle valeur de retour. Deuxième * Représente n'importe quelle méthode. … Correspond à n'importe quel nombre de paramètres. Si la classe cible et l'interface sont dans le même paquet que la section , Le nom du paquet peut être omis.

2).execution public * ArithmeticCalculator.*(…): Ça correspond ArithmeticCalculator Toutes les méthodes publiques de l'interface.

3).execution public double ArithmeticCalculator.*(…): Ça correspond ArithmeticCalculator Retour au milieu double Méthode des valeurs de type

4).execution public double ArithmeticCalculator.*(double, …): Le premier paramètre correspondant est double Type de méthode, … Correspond à n'importe quel nombre de paramètres de n'importe quel type

5).execution public double ArithmeticCalculator.*(double, double): Le type de paramètre correspondant est double, double Type de méthode.

6. Spécifiez la priorité de la section

1). Lorsque plus d'une tangente est appliquée au même point de connexion , Sauf indication contraire, Sinon, leur priorité est incertaine .

2). La priorité de la Section peut être atteinte en Ordered Interface ou utilisation @Order Note spécifiant.

3).Réalisation Ordered Interface, getOrder() Retour de la méthodePlus la valeur est faible, Plus la priorité est élevée.

4).Si utilisé @Order Notes, Le numéro de série apparaît dans l'annotation

7.Réutiliser la définition du point d'entrée

1).En préparation AspectJ En coupe , Vous pouvez écrire des expressions pointcut directement dans les annotations de notification . Mais la même expression tangente peut être répétée dans plusieurs notifications .

2).In AspectJ En tangente, Peut passer @Pointcut Notes Une façon simple de déclarer un point de coupure . Le corps de la méthode d'entrée est généralement vide , Parce qu'il n'est pas raisonnable de mélanger la définition du point d'entrée avec la logique de l'application .

3). Le Contrôleur d'accès de la méthode point - cut contrôle également la visibilité de ce point - cut . Si le point de coupure doit être partagé entre plusieurs tangentes , Il est préférable de les regrouper dans une classe commune . Dans ce cas,, Ils doivent être déclarés comme public. En introduisant ce point d'entrée , Le nom de la classe doit également être inclus . Si la classe n'est pas dans le même paquet que cette section , Doit également contenir le nom du paquet .

4). D'autres notifications peuvent introduire ce point d'entrée par le nom de la méthode .

8.CAS

Une section peut comprendre une ou plusieurs notifications .

package com.cm.ch05.aop;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/* * Log tangent * Tangente:Préoccupations transversales * 1. Ajouter la classe actuelle à IOCDans le récipient:@Component * 2. Rendre la classe actuelle disponible pour l'utilisation AOP:@Aspect * 3.@Order(2) Priorité de la section, Plus la valeur est petite, plus elle est exécutée en premier  */
@Order(2)
@Component
@Aspect
public class LogAspect {
    

	// Point d'entrée commun :Adoption @Pointcut  L'annotation exprime un point de coupure en une méthode simple .  Le corps de la méthode d'entrée est généralement vide 
	@Pointcut("execution(public int com.cm.ch05.aop.CountImpl.*(int,int))")
	public void declarePointcut(){
    }


	/* * Pré - notification:@Before("execution(public int com.cm.ch05.aop.CountImpl.*(int,int))") * 1.@Before * 2.Tangentepointcut:("execution(xxx)") * 3.Syntaxe simplifiée:@Before("execution(* CountImpl.*(..))") * Le premier*: N'importe quel accès et n'importe quelle valeur de retour  * Deuxième*: Spécifie n'importe quelle méthode sous la classe  * Troisième..: Correspond à n'importe quel paramètre  * PS:Sous le même sac., Le nom du paquet peut être omis  * 4.JoinPoint Point de connexion: Obtenir le nom de la méthode actuellement consultée ,Liste des paramètres */
	//@Before("execution(* CountImpl.*(..))")
	@Before("declarePointcut()")
	public void beforeAdvice(JoinPoint jp){
    
		//Nom de la méthode
		String methodName = jp.getSignature().getName();
		//Liste des paramètres
		List<Object> args = Arrays.asList(jp.getArgs());
		System.out.println("Suivi des journaux:the method "+methodName+" begin with "+args);
	}

	//Retour à la notification:returning Le nom de la valeur doit correspondre au nom du paramètre dans la méthode 
	//@AfterReturning(pointcut="execution(* CountImpl.*(..))",returning="result")
	@AfterReturning(pointcut="declarePointcut()",returning="result")
	public void AfterReturningAdvice(JoinPoint jp,Object result) throws Throwable{
    
		//Nom de la méthode
		String methodName = jp.getSignature().getName();
		System.out.println("Suivi des journaux:the method "+methodName+" end with "+result);
	}

	//Avis d'exception:throwing Le nom de la valeur doit correspondre au nom du paramètre dans la méthode 
	//@AfterThrowing(value="execution(* CountImpl.*(..))",throwing="ex")
	@AfterThrowing(pointcut="declarePointcut()",throwing="ex")
	public void AfterThrowingAdvice(JoinPoint jp,Exception ex){
    
		//Nom de la méthode
		String methodName = jp.getSignature().getName();
		System.out.println("Suivi des journaux:the method "+methodName+" occurn exception:"+ex);
	}

	//Post - notification
	//@After("execution(* CountImpl.*(..))")
	@After("declarePointcut()")
	public void AfterAdvice(JoinPoint jp){
    
		//Nom de la méthode
		String methodName = jp.getSignature().getName();
		System.out.println("Suivi des journaux:the method "+methodName+" end with");
	}

	//Notification surround
	//@Around("execution(* CountImpl.*(..))")
	public Object AroundAdvice(ProceedingJoinPoint pjp){
    
		String methodName = pjp.getSignature().getName();
		List<Object> args = Arrays.asList(pjp.getArgs());
		Object result = null;
		try {
    
			//Pré - notification
			System.out.println("Suivi des journaux:the method "+methodName+" begin with "+args);
			result = pjp.proceed();
			//Retour à la notification
			System.out.println("Suivi des journaux:the method "+methodName+" end with "+result);
		} catch (Throwable e) {
    
			//Notification surround
			System.out.println("Suivi des journaux:the method "+methodName+" occurs exception:"+e.getMessage());
		}
		//Post - notification
		System.out.println("Suivi des journaux:the method "+methodName+" end with");
		return result;
	}
}

9.Tests

package com.cm.ch05.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    

	public static void main(String[] args) throws Exception {
    
		
		ApplicationContext ac = 
				new ClassPathXmlApplicationContext("beans_aop.xml");
		
		ICount count = (ICount)ac.getBean("countImpl");
    System.out.println(count.getClass().getName());
		
		int result1 = count.add(1, 2);
		System.out.println(result1);
		
		int result2 = count.div(0, 2);
		System.out.println(result2);
	}

}

3.4、Spring AOP XMLÉdition

1.Basé sur XML ---- Déclarer la section

1.Lorsqu'il est utilisé XML Lors de la Déclaration de la section , Besoin de Importer dans l'élément racine aop Schema

2.In Bean Dans le profil, Tous les Spring AOP La configuration doit être définie à aop:config Élément intérieur. Pour chaque section, Créer un aop:aspect Element to Reference Backend for Concrete tangent Implementation Bean Exemple.

3.Tangente Bean Il doit y avoir un identificateur , Pour aop:aspect Référence de l'élément

2.Basé sur XML ---- Déclarez le point d'entrée

1.Utilisation du point d'entréeaop:pointcutDéclaration de l'élément

2.Le point d'entrée doit être défini à aop:aspect Sous l'élément, Ou directement défini dans aop:config Sous l'élément.

1).Défini dans aop:aspect Sous l'élément: Valable uniquement pour la section courante

2).Défini dans aop:config Sous l'élément: Valable pour toutes les sections

3.Basé sur XML De AOP La configuration ne permet pas de faire référence à un autre point d'entrée par nom dans une expression point d'entrée.

3.Basé sur XML ---- Avis de déclaration

1.In aop Schema Moyenne, Chaque type de notification correspond à un XML Élément.

2.L'élément de notification doit être utilisé Pour citer le point d'entrée, Ou Intégration directe des expressions pointcut. method La propriété spécifie le nom de la méthode de notification dans la classe de section.

4.CAS

3.5、Spring AOP Configurer la classe+Version annotée

MyConfigCatégorie

//OuvertAspectProgrammation orientée tangente proxyTargetClass = trueOuvertCGLIBAgent dynamique
@EnableAspectJAutoProxy(proxyTargetClass = true)
//Configurer le paquet Scan
@ComponentScan("com.igeek.aop.ch03.config")
//La classe actuelle est une classe de configuration
@Configuration
public class MyConfig {
    

    /** * @Bean Notes * 1. Placer la valeur de retour de la méthode courante dans IOCConteneur pour la gestion * 2.Peu importe.getBeanCombien de fois?, Obtenir est le seul exemple ,Parce queSpring IOCConteneur,Instance unique par défaut * 3. L'Instance courante est placée dans IOCDerrière le conteneur, Le nom actuel de la méthode est utilisé comme BeanNamePour l'utiliser * 4.@BeanDans la configuration de la classe, Créer un composant avec  */
    //@Scope("prototype")
    @Bean
    public ArithmeticCalculator c(){
    
        return new ArithmeticCalculator();
    }

}

TestCatégorie

public class Test {
    

    public static void main(String[] args) {
    
        //1.CréationIOCConteneur AnnotationConfigApplicationContext
        ApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);

        //2.Obtenir des exemplesbean
        ArithmeticCalculator proxy = ac.getBean(ArithmeticCalculator.class);
        //com.igeek.aop.ch03.config.ArithmeticCalculator$$EnhancerBySpringCGLIB$$b304c68a
        System.out.println(proxy.getClass().getName());

        //3.Exemples d'utilisationbean
        int result1 = proxy.add(10, 20);
        System.out.println("result1 = "+result1);

        int result2 = proxy.div(-10, 5);
        System.out.println("result2 = "+result2);
    }

}

Quatre.SpringGestion des transactions

1.Introduction à la transaction

1). La gestion des transactions est une technologie essentielle au développement d'applications au niveau de l'entreprise , Utilisé pour assurer l'intégrité et la cohérence des données.

2). Une transaction est une série d'actions , Ils sont considérés comme une unit é de travail séparée . Toutes ces actions doivent être terminées., Soit ça ne marche pas.

3). Quatre attributs clés de la transaction (ACID)

Atomicité(atomicity): Une transaction est une opération atomique, Se compose d'une série d'actions. L'atomicité de la transaction garantit que l'action est complète ou totalement inopérante .

Cohérence(consistency): Une fois toutes les opérations terminées, La transaction est engagée . Les données et les ressources sont dans un état de cohérence qui répond aux règles opérationnelles .

Isolement(isolation): Il peut y avoir beaucoup de transactions qui traitent les mêmes données en même temps, Donc tout doit être séparé des autres. , Prévenir la corruption des données.

Persistance(durability): Une fois la transaction terminée, Quelles que soient les erreurs système qui se produisent, Aucun de ses résultats ne devrait être affecté. En général, Le résultat de la transaction est écrit dans la mémoire de persistance.

2.Spring Gestion des transactions dans

1). En tant que cadre d'application au niveau de l'entreprise , Spring Gestion des différentes transactions API Une couche d'abstraction est définie ci - dessus. Les développeurs d'applications n'ont pas besoin de comprendre la gestion des transactions sous - jacente API, On peut l'utiliser. Spring Mécanisme de gestion des transactions pour.

2).Spring Prise en charge de la gestion programmatique des transactions, La gestion déclarative des transactions est également prise en charge.

3).Gestion des transactions de programmation: Intégrer le Code de gestion des transactions dans les méthodes opérationnelles pour contrôler l'engagement et le report des transactions . Lors de la gestion programmatique des transactions , Un code de gestion de transaction supplémentaire doit être inclus dans chaque opération de transaction .

4).Gestion déclarative des transactions: Mieux que la gestion programmatique des transactions dans la plupart des cas . Il sépare le Code de gestion des transactions de l'approche opérationnelle , Mettre en œuvre la gestion des transactions de manière déclarative. La gestion des transactions en tant que préoccupation transversale , C'est bon.Adoption AOP Modularité des méthodes. Spring Adoption Spring AOP Le cadre soutient la gestion déclarative des transactions.

3.Spring Gestionnaire de transaction en

1.Spring Gérer à partir de différentes transactions API Un ensemble complet de mécanismes transactionnels est résumé dans . Les développeurs n'ont pas à comprendre les transactions sous - jacentes API, Vous pouvez utiliser ces mécanismes transactionnels . Avec ces mécanismes transactionnels , Le Code de gestion des transactions peut être indépendant d'une technologie de transaction spécifique .

2.Spring Classe abstraite de gestion des transactions de base pour TransactionManager,Il encapsule un ensemble d'approches indépendantes de la technologie pour la gestion des transactions. Quelle que soit l'utilisation Spring Quelle politique de gestion des transactions(Programmation ou déclaration), Les gestionnaires de transactions sont nécessaires.

3.DataSourceTransactionManager:Une seule source de données doit être traitée dans l'application, Et à travers JDBC Accès. Le gestionnaire de transaction prend le Bean Une déclaration de forme est faite à Spring IOC Dans le récipient.

4.@Transactional Annotation gérer les transactions de façon déclarative

4.1 Modifierpom.xml

<!-- IntroductionspringDeJDBCDépendance -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.3.4.RELEASE</version>
</dependency>

<!-- Tests unitaires -->
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.10</version>
</dependency>

4.2 NouveauspringProfil de base pourbeans_trans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	
	<!-- Importer un fichier de propriétés -->
	<context:property-placeholder location="classpath:db.properties"/>
	
	<!--  Ajouter un paquet de scan  -->
	<context:component-scan base-package="com.cm.ch06.trans"></context:component-scan>

	<!-- ConfigurationC3P0Pool de connexion pour -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${db.name}"></property>
		<property name="password" value="${db.password}"></property>
		<property name="jdbcUrl" value="${db.jdbcUrl}"></property>
		<property name="driverClass" value="${db.driverClass}"></property>
	</bean>

	<!-- ConfigurationJdbcTemplate -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- ConfigurationNamedParameterJdbcTemplate, Pas de constructeur sans paramètres , Doit fonctionner comme injection de constructeur  -->
	<bean id="namedParam" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
		<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
	</bean>

	<!-- spring JDBC Gestionnaires de transactions pris en charge  DataSourceTransactionManager -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!--  Déclaration de soutien   Gestion annotée des transactions  -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

4.3 Avec @Transactional Annotation gérer les transactions de façon déclarative

1). Sauf avec des points d'entrée , Notification et renforcement Bean Hors transaction déclarée dans le profil , Spring Permet également une utilisation simple @Transactional Annotation pour marquer la méthode de transaction .

2). Pour définir la méthode comme supportant la transaction , Peut être ajouté à une méthode @Transactional Notes. Selon Spring AOP Mécanisme fondé sur les agents , Seules les méthodes publiques peuvent être marquées .

3). Peut être ajouté au niveau de la méthode ou de la classe @Transactional Notes. En appliquant cette annotation à la classe , Toutes les méthodes publiques de cette classe seront définies pour soutenir le traitement des transactions .

4).In Bean Il suffit d'activer tx:annotation-drivenÉlément, Et il suffit de spécifier le gestionnaire de transaction .

5). Si le nom du processeur de transaction est transactionManager, Juste là.tx:annotation-driven Omis dans l'élément transaction-manager Propriétés. Cet élément détecte automatiquement le processeur de transaction avec ce nom .

4.4 Propriétés de propagation des transactions

Lorsque la méthode de transaction est appelée par une autre méthode de transaction, Vous devez préciser comment la transaction doit se propager. Par exemple: La méthode peut continuer à fonctionner dans une transaction existante, Une nouvelle transaction peut également être ouverte, Et fonctionne dans ses propres transactions.

Le comportement de propagation d'une transaction peut être spécifié par l'attribut propagation.

REQUIRED Comportement de diffusion

1). Par exemple, lorsque la méthode d'achat purchase() Par une autre méthode de transaction checkout() Au moment de l'appel, Il fonctionne par défaut dans une transaction existante . Ce comportement de propagation par défaut est REQUIRED. Donc, dans checkout() Il n'y a qu'une seule transaction à l'intérieur des limites de début et de fin de la méthode . Cette affaire ne concerne que checkout() Soumis à la fin de la méthode .

2). Les propriétés de propagation des transactions peuvent être trouvées à @Transactional Annotated propagation Défini dans la propriété

REQUIRES_NEW Comportement de diffusion

Un autre comportement de transmission courant est REQUIRES_NEW. Cela signifie que la méthode doit démarrer une nouvelle transaction , Et fonctionne dans le cadre de ses propres transactions. Si une transaction est en cours, Tu devrais le suspendre. .

Problèmes causés par des transactions concurrentes

1). Lorsque plusieurs transactions dans la même application ou dans différentes applications sont exécutées simultanément sur le même ensemble de données , De nombreux problèmes inattendus peuvent survenir

2). Les problèmes causés par les transactions simultanées peuvent être classés en trois types: :

Sale lecture.: Pour Deux choses T1, T2, T1 A été lu par T2 Champs mis à jour mais non encore soumis. Après, Si T2 Retour en arrière, T1Le contenu Lu est temporaire et invalide.

Non répétable:Pour Deux choses T1, T2, T1 Un champ a été lu, Et puis T2 Ce champ a été mis à jour. Après, T1Lisez à nouveau le même champ, La valeur est différente.

Lecture fictive:Pour Deux choses T1, T2, T1 Un champ a été lu à partir d'un tableau, Et puis T2 De nouvelles lignes ont été insérées dans le tableau. Après, Si T1 Lisez à nouveau le même tableau, Et quelques lignes de plus.

4.5 Niveau d'isolement de la transaction

1).En théorie,, Les transactions doivent être complètement séparées les unes des autres, Pour éviter les problèmes causés par des transactions simultanées. Et pourtant, Cela aurait un impact énorme sur la performance, Parce que les transactions doivent être exécutées dans l'ordre.

2).Dans le développement réel, Pour améliorer les performances, La transaction se déroule à un niveau d'isolement inférieur.

3).Le niveau d'isolement d'une transaction peut être spécifié par l'attribut d'isolement de la transaction

4).Spring Niveaux d'isolement des transactions pris en charge

5).Le niveau d'isolement des transactions est supporté par le moteur de base de données sous - jacent, Plutôt que le support d'une application ou d'un cadre.

Oracle Soutien 2 Niveau d'isolement des transactions:READ_COMMITED , SERIALIZABLE

Mysql Prise en charge de ce qui précède 4Niveau d'isolement des transactions.

6). Définir les propriétés des transactions isolées

Avec @Transactional Les annotations peuvent être utilisées pour gérer les transactions de façon déclarative à @Transactional De isolation Définir le niveau d'isolement dans la propriété.

4.6 Définir les propriétés de la transaction de rollback

1). Par défaut, seules les exceptions non vérifiées (RuntimeExceptionEtErrorException de type) Peut entraîner un retour en arrière de la transaction . Et les anomalies vérifiées ne .

2). Les règles de ROLLBACK pour les transactions peuvent être adoptées par @Transactional Annotated rollbackFor Et noRollbackFor Propriétés à définir. Ces deux propriétés sont déclarées comme Class[] Type, Vous pouvez donc spécifier plusieurs classes d'exception pour ces deux propriétés .

rollbackFor: Un ROLLBACK doit être effectué lorsqu'il est rencontré

4.7 Attributs timeout et readonly

1.Parce que les transactions peuvent obtenir des serrures sur les lignes et les tables, Par conséquent, les transactions longues peuvent prendre des ressources, Et a un impact sur le rendement global.

2.Si une chose ne lit que des données mais ne les modifie pas, Le moteur de base de données peut optimiser cette transaction.

3.Attribut de transaction Timeout: timeoutPropriétés,Combien de temps la transaction peut - elle durer jusqu'à ce qu'elle soit forcée de reculer?. Cela empêche les transactions à long terme d'utiliser des ressources.

4.Propriétés des transactions en lecture seule: readOnlyLa propriété esttrueHeure,Indique que cette transaction ne lit que les données mais ne les met pas à jour, Cela aide le moteur de base de données à optimiser les transactions.

5. Définir les propriétés de transaction timeout et readonly

Les attributs timeout et Read Only peuvent être trouvés à l'adresse suivante: @Transactional Défini dans les notes . L'attribut timeout est calculé en secondes .

4.8 CAS

Besoins:

1).InterfaceBookShopDAOMoyenne:

// Obtenir le prix unitaire du livre par numéro de livre

public int findPriceByBookId(int bookId);

// Mise à jour de l'inventaire des livres par numéro de livre , Réduire l'inventaire correspondant au numéro du livre 1

public void updateStock(int bookId);

// .Mettre à jour le solde de l'utilisateur par nom d'utilisateur ,FaireusernameDebalance-price

public void updateAccount(String username,int price);

2).InterfaceBookShopServiceMoyenne:

// Acheter un livre en fonction de son numéro et de son nom d'utilisateur :

// Un utilisateur ne peut acheter qu'un seul livre à la fois (Fonctionnement:1. Solde du compte moins prix unitaire du livre 2. L'inventaire des livres diminue 1)

public void purchase(String username,int bookId);

ImportersqlDocumentation,Initialisation des données: Création de la structure du tableau t_accountTableau des comptes t_bookListe des livres t_stockInventaire des livres

daoCouche

IBookShopDaoInterface

package com.cm.ch06.trans.dao;

public interface IBookShopDao {
    

	//SelonbookId Prix d'acquisition du livre 
	public int selectPrice(int bookId);
	//SelonbookIdMise à jour de l'inventaire
	public void updateStock(int bookId);
	//Selonusername,priceMise à jour du solde du compte
	public void updateBalance(String username, int price);
	
}

BookShopDaoImpl Catégorie

package com.cm.ch06.trans.dao;

import javax.annotation.Resource;

import com.cm.ch06.trans.exception.AccountException;
import com.cm.ch06.trans.exception.BookStockException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository("bookShopDao")
public class BookShopDaoImpl implements IBookShopDao {
    
	@Resource
	private JdbcTemplate jdbcTemplate;
	
	@Override
	public int selectPrice(int bookId) {
    
		String sql = "select price from t_book where bookId = ?";
		Integer price = jdbcTemplate.queryForObject(sql, Integer.class, bookId);
		return price;
	}

	@Override
	public void updateStock(int bookId) {
    
		String s = "select stock from t_stock where bookId=?";
		int stock = jdbcTemplate.queryForObject(s, Integer.class, bookId);
		if(stock<=0){
    
			throw new BookStockException("Insuffisance des stocks!!!");
		}
		
		String sql = "update t_stock set stock=stock-1 where bookId=?";
		jdbcTemplate.update(sql, bookId);
	}

	@Override
	public void updateBalance(String username, int price) {
    
		String s = "select balance from t_account where username=?";
		Integer balance = jdbcTemplate.queryForObject(s, Integer.class, username);
		if(balance<price){
    
			throw new AccountException("Solde insuffisant du compte!!!");
		}
		
		String sql = "update t_account set balance=balance-? where username=?";
		jdbcTemplate.update(sql, price,username);
	}

}

serviceCouche

ICashierService Interface

package com.cm.ch06.trans.service;

import java.util.List;

public interface ICashierService {
    

	// Check - out du client 
	public void cash(String username, List<Integer> bookIds);
}

IBookShopService Interface

package com.cm.ch06.trans.service;

public interface IBookShopService {
    

	// Acheter des livres par nom de compte et numéro de livre 
	public void purchase(String username, int bookId);
}

CashierServiceImpl Catégorie

package com.cm.ch06.trans.service;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("cashierService")
public class CashierServiceImpl implements ICashierService {
    
	@Resource
	private IBookShopService bookShopService;
	
	@Transactional
	@Override
	public void cash(String username, List<Integer> bookIds) {
    
		for (Integer bookId : bookIds) {
    
			bookShopService.purchase(username, bookId);
		}
	}

}

BookShopServiceImpl Catégorie

package com.cm.ch06.trans.service;

import java.io.IOException;
import java.sql.SQLException;

import javax.annotation.Resource;

import com.cm.ch06.trans.dao.IBookShopDao;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("bookShopService")
public class BookShopServiceImpl implements IBookShopService {
    
	@Resource
	private IBookShopDao bookShopDao;
	
	
	// Prise en charge de la gestion annotée des transactions 
	@Transactional(propagation=Propagation.REQUIRES_NEW,
			isolation=Isolation.READ_COMMITTED,
			rollbackFor={
    IOException.class,SQLException.class},
			noRollbackFor={
    ArithmeticException.class},
			readOnly=false,
			timeout=3)
	@Override
	public void purchase(String username, int bookId) {
    
// try {
    
// Thread.sleep(5000);
// } catch (InterruptedException e) {
    
// e.printStackTrace();
// }
		int price = bookShopDao.selectPrice(bookId);
		bookShopDao.updateStock(bookId);
		bookShopDao.updateBalance(username, price);
	}

}

Gestion des exceptions

1).SeulementRuntimeException Et n'a pas été try catch Seules les exceptions traitées feront reculer la transaction

public class BookStockException extends  RuntimeException {
    
    public BookStockException() {
    
    }

    public BookStockException(String message) {
    
        super(message);
    }
}

public class AccountException extends  RuntimeException {
    
    public AccountException() {
    
    }

    public AccountException(String message) {
    
        super(message);
    }
}

2). Si l'exception hérite Exception,Ça pourrait être dansserviceLancer vers le Haut,Non, non.try…catch, Spécifié par ExceptionType, Peut revenir en arrière .

 @Transactional(rollbackFor={
    Exception.class})

Catégorie d'essai TestSpringTrans

package com.cm.ch06.trans.test;

import org.junit.Test;
import java.util.Arrays;
import com.cm.ch06.trans.dao.IBookShopDao;
import com.cm.ch06.trans.service.IBookShopService;
import com.cm.ch06.trans.service.ICashierService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class TestSpringTrans {
    

	private ApplicationContext ac;
	private IBookShopDao bookShopDao;
	private IBookShopService bookShopService;
	private ICashierService cashierService;
	
	{
    
		ac = new ClassPathXmlApplicationContext("beans_trans.xml");
		bookShopDao = (IBookShopDao)ac.getBean("bookShopDao");
		bookShopService = (IBookShopService)ac.getBean("bookShopService");
		cashierService = (ICashierService)ac.getBean("cashierService");
	}

	@Test
	public void testSelectPrice() {
    
		int price = bookShopDao.selectPrice(1);
		System.out.println(price);
	}
	
	@Test
	public void testUpdateStock() {
    
		bookShopDao.updateStock(1);
	}
	
	@Test
	public void testUpdateBalance() {
    
		bookShopDao.updateBalance("Zhang San", 40);
	}
	
	@Test
	public void testPurchase() {
    
		// Il peut y avoir une situation , Acheter un livre quand le solde est insuffisant , Le solde n'a pas changé , Mais les stocks continuent de diminuer 
		bookShopService.purchase("Zhang San", 1);
	}
	
	@Test
	public void testCash() {
    
		//Il peut y avoir une situation, Quand le solde est insuffisant pour acheter tous les livres , Faire reculer la transaction , Aucun livre n'a été acheté avec succès 
		cashierService.cash("Zhang San", Arrays.asList(1,2));
	}

}

5.SpringUtilisé dansxml Mode fichier configurer la transaction

5.1 Gérer les transactions de façon déclarative avec un avis de transaction

1). La gestion des transactions est une préoccupation transversale

2).Pour Spring 2.x Activer la gestion déclarative des transactions , Peut passer tx Schema Défini danstx:advice Avis de transaction de déclaration d'élément , Pour ce faire, il faut d'abord Schema Définition ajoutée à De l'élément racine .

3). Après avoir déclaré un avis de transaction , Vous devez l'associer au point d'entrée . Puisque l'avis de transaction a été envoyé à aop:config Élément déclaré à l'extérieur , Il ne peut donc pas être directement associé au point d'entrée . Il faut donc aop:config L'élément indique qu'une notification d'amplificateur est associée à une coupure de point .

4).Parce que Spring AOP C'est une approche par procuration , Ainsi, seule la méthode publique peut être améliorée . Donc,, Seules les méthodes publiques peuvent passer Spring AOP Gestion des transactions.

5.2 Exemple de code de transaction de gestion déclarative avec notification de transaction

5.3 Dans l'avis de transaction , Ça pourrait être dans tx:method Configurer les propriétés de propagation dans l'élément

5.4 Dans l'avis de transaction , Ça pourrait être dans tx:method Niveau d'isolement spécifié dans l'élément

5.5 Dans l'avis de transaction , Ça pourrait être dans tx:method Définir les attributs de transaction de ROLLBACK dans l'élément

S'il y a plus d'une exception , Séparer par des virgules.

5.6 Dans l'avis de transaction , In tx:method Définir les attributs timeout et Read Only dans l'élément

6.Spring Utiliser la classe de configuration dans + Comment configurer la transaction

MyConfig.java

//Ouvrir le gestionnaire de transaction
@EnableTransactionManagement
// Ajouter un paquet de scan 
@ComponentScan("com.igeek.ch27.config")
//Chargement du fichier de propriétés externes
@PropertySource("db.properties")
//Configurer la classe
@Configuration
public class MyConfig {
    

    /** * @Bean Configurer la source de données * 1. Placer la valeur de retour de la méthode courante dans IOCGestion en conteneur,Par défautsingletonCas unique * 2. Utilisez le nom de la méthode courante comme BeanNameDans un contenant */
    @Bean
    public DataSource dataSource(
            @Value("${db.name}") String name,
            @Value("${db.password}") String password,
            @Value("${db.jdbcUrl}") String jdbcUrl,
            @Value("${db.driverClass}") String driverClass
    ) throws PropertyVetoException {
    
        //Créer une source de données
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        // Configurer la connexion associée 
        dataSource.setUser(name);
        dataSource.setPassword(password);
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setDriverClass(driverClass);
        //Retour à la source des données
        return dataSource;
    }

    /** * @Bean ConfigurationJdbcTemplate * 1. Placer la valeur de retour de la méthode courante dans IOCGestion en conteneur,Par défautsingletonCas unique * 2. Utilisez le nom de la méthode courante comme BeanNameDans un contenant * 3. Une fois qu'il y a un paramètre formel dans la méthode ,@BeanIl sera là.IOC Instance trouvée dans le conteneur et injectée  */
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
    
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        return jdbcTemplate;
    }


    // Placer l'instance du gestionnaire de transaction IOCGestion en conteneur
    @Bean
    public PlatformTransactionManager platformTransactionManager(DataSource dataSource){
    
        DataSourceTransactionManager dataSourceTransactionManager =
                new DataSourceTransactionManager(dataSource);
        return dataSourceTransactionManager;
    }
}

TransactionTest.java Catégorie d'essai

public class TransactionTest {
    

    @Test
    public void test() throws IOException {
    
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
        
        int count = ac.getBeanDefinitionCount();
        System.out.println(count);  //17
        String[] names = ac.getBeanDefinitionNames();
        //dataSource jdbcTemplate platformTransactionManager myConfig bookShopDaoImpl bookShopServiceImpl
        System.out.println(Arrays.toString(names));
        
        BookShopServiceImpl service = ac.getBean(BookShopServiceImpl.class);
        service.purchase("Zhang San",1);
    }

}

Cinq.Spring5 Introduction de nouvelles caractéristiques

Un..Spring FrameWork 5.0Nouvelles fonctionnalités

La mise à jour vers la nouvelle version du cadre peut se référer à .Spring git.

Liste des contenus

Spring 5.x Nouvelles fonctionnalités du cadre

Spring 4.x Nouvelles fonctionnalités du cadre

Spring 3.x Nouvelles fonctionnalités du cadre

1.JDK 8+EtJava EE7+Version précédente

  • Le Code de l'ensemble du cadre est basé surjava8
  • Amélioration de la lisibilité grâce à l'utilisation de caractéristiques telles que les génériques
  • C'est exact.java8Améliorer le support de code direct
  • Compatible avec l'exécutionJDK9
  • Java EE 7APIBesoinSpringPrise en charge des modules associés
  • Compatible avec l'exécutionJava EE8 API
  • Paquets annulés,Classes et méthodes
  • Sac beans.factory.access
  • Sac dbc.support.nativejdbc
  • Despring-aspects Le module a supprimé le paquetmock.staicmock, Il n'est pas question de AnnotationDrivenStaticEntityMockingControlSoutien
  • De nombreuses classes et méthodes non recommandées sont supprimées de la base de code

2.Caractéristiques essentielles

JDK8Amélioration de:

  • Accès àResuouceDisponible àgetFileOuisFileAbstractions défensives
  • L'accès aux paramètres de la méthode valide est basé surjava 8Amélioration de la réflexion
  • InSpringDéclaration ajoutée à l'interface centraledefaultLe support de la méthode est toujours utiliséJDK7 CharsetEtStandardCharsetsAmélioration de
  • Compatible avecJDK9
  • Spring 5.0Le cadre est livré avec l'encapsulation universelle du Journal
  • Instanciation continueviaConstructeur(Gestion des exceptions modifiée)
  • Spring 5.0Le cadre est livré avec l'encapsulation universelle du Journal
  • spring-jclRemplace le journal général,La réécriture est toujours prise en charge
  • Détection automatiquelog4j2.xml, SLF4J, JUL(java.util.Logging)Au lieu d'un autre soutien
  • Accès àResuouceDisponible àgetFileOuisFileAbstractions défensives
  • Basé surNIODereadableChannelCette nouvelle fonctionnalité est également disponible

3.Conteneur Central

  • Prise en charge de l'index des composants candidats(La numérisation des variables d'environnement peut également être prise en charge)
  • Soutien@NullableNotes
  • Style fonctionnelGenericApplicationContext/AnnotationConfigApplicationContext
  • Soutien de basebean APIInscription
  • Utilisation au niveau de l'interfaceCGLIBQuand le proxy dynamique,Fournir des choses,Cache,Test d'annotation asynchrone
  • XMLConfigurer le flux scope
  • Spring WebMVC
  • TousServlet 3.1 La signature est prise en charge àSpring-provied FilterRéalisation
  • InSpring MVC ControllerLa méthode soutientServlet4.0 PushBuilderParamètres
  • Liaison de données pour plusieurs objets immuables(Kotlin/Lombok/@ConstructorPorties)
  • Soutienjackson2.9
  • SoutienJSONBINDAPI
  • Soutienprotobuf3
  • SoutienReactor3.1 FluxEtMono

4.SpringWebFlux

  • Nouveauspring-webfluxModule,L'un est basé surreactiveDespring-webmvc, Non - blocage asynchrone complet ,Conçu pour utiliserenent-loop Modèle d'exécution et modèle traditionnel de pool de Threads .
  • ReactiveDescription inspring-core Comme le codage et le décodage
  • spring-core Infrastructures connexes ,Par exemple,Encode EtDecoder Peut être utilisé pour encoder et décoder les flux de données ;DataBuffer Peut être utiliséjava ByteBufferOuNetty ByteBuf;ReactiveAdapterRegistry Le support de la couche transport peut être fourni pour les bibliothèques associées .
  • Inspring-web Le sac contient HttpMessageReadeEtHttpMessageWrite

5. Amélioration des essais

  • C'est fait.JUnit 5’s JuptierModule de programmation et d'expansionSpring TestContextCadre
  • SpringExtension:- Oui.JUnit Plusieurs extensibles APIUne réalisation de, Fournit une vue d'ensemble Spring TestContext FrameworkAppui,Utiliser@ExtendWith(SpringExtension.class)Référence à l'annotation.
  • @SpringJunitConfig:Une annotation composée
  • @ExtendWith(SpringExtension.class) DeJunit Jupit
  • @ContextConfiguration DeSrping TestContextCadre
  • @DisabledIf Si la valeur de la propriété fournie est true Représentation ou substituant pour ,Signal: La classe d'essai annotée ou la méthode d'essai est désactivée
  • InSpring TestContext Prise en charge des tests parallèles dans le cadre
  • Voir les détailsTest Chapitre AdoptionSpringRunnerInSring TestContext Soutien dans le cadre TestNG, Junit5, Nouveau rappel d'essai avant et après l'exécution .
  • Intestexecutionlistener APIEttestcontextmanagerNouveaubeforetestexecution()Etaftertestexecution()Rappel.MockHttpServletRequestAjoutégetContentAsByteArray()EtgetContentAsString() Méthode d'accès au corps de la demande
  • Si l'encodage des caractères est défini à mockDemande,Inprint()Etlog() La méthode peut être imprimée Spring MVC TestDeredirectedUrl()EtforwardedUrl() .La méthode supporte les expressions avec des variables URLModèle.
  • XMLUnit Mise à jour vers2.3Version.

2.. Utilisation de nouvelles fonctionnalités

Tout Spring5 Le Code du cadre est basé sur Java8,Compatible avec l'exécution JDK9,De nombreuses classes et méthodes non recommandées sont supprimées de la base de code

1.Spring 5.0 Le cadre est livré avec l'encapsulation universelle du Journal

(1)Spring5 Supprimé Log4jConfigListener,Utilisation officielle recommandée Log4j2

(2)Spring5 Intégration des cadres Log4j2

Première étape:Modifierpom.xml,Introduire des dépendances

<!-- Introduction -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.11.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.11.2</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.30</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.11.2</version>
</dependency>

Deuxième étape Création log4j2.xml Profil

<?xml version="1.0" encoding="UTF-8"?>
<!--Niveau du journal et ordre de priorité: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration Derrière. status Pour le réglage log4j2 Production interne d'informations,Peut ne pas définir, Quand il est réglé à trace Heure,Je vois. log4j2 Divers produits détaillés internes--> 
<configuration status="INFO">
 <!--Définir tout d'abord appender-->
 <appenders>
 <!--Sortie des informations du Journal vers la console-->
 <console name="Console" target="SYSTEM_OUT">
 <!--Contrôle le format de sortie du Journal-->
 <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %- 5level %logger{36} - %msg%n"/>
 </console>
 </appenders>
 <!--Et ensuite définir logger,Seulement la définition logger Et introduit appender,appender Pour entrer en vigueur-->
 <!--root:Journal racine utilisé pour spécifier l'élément,S'il n'est pas précisé séparément Logger,Sera utilisé root En tant que Sortie du journal par défaut-->
 <loggers>
 <root level="info">
 <appender-ref ref="Console"/>
 </root>
 </loggers>
</configuration>

Troisième étape Écrire une classe de test

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogTest {
    

    private static final Logger logger = LoggerFactory.getLogger(LogTest.class);

    public static void main(String[] args) {
    
        logger.info("LogTest infoNiveau");
        logger.warn("LogTest warnNiveau");
    }

}

2.Spring5Support du conteneur de base du cadre@NullableNotes

(1)@Nullable Les annotations peuvent être utilisées sur la méthode,Propriétés ci - dessus,Paramètre ci - dessus,Le retour de la méthode de représentation peut être vide,La valeur de l'attribut peut

Vide,La valeur du paramètre peut être vide

(2)Note utilisée sur la méthode,La valeur de retour de la méthode peut être vide

@Nullable
String getId();

(3)Les annotations sont utilisées dans les paramètres de la méthode,Les paramètres de la méthode peuvent être nuls

public <T> void regist(@Nullable String name){
    
    //...
}

(4)Les annotations sont utilisées sur les propriétés,La valeur de la propriété peut être vide

@Nullable
private String name;

3.Spring5Le conteneur central supporte le style fonctionnelGenericApplicationContext

//Style fonctionnel créer des objets,À vous. spring Gérer
@Test
public void testGenericApplicationContext() {
    
     //1 Création GenericApplicationContext Objet
     GenericApplicationContext context = new GenericApplicationContext();
     //2 Appelez context Enregistrement des objets de méthode pour
     context.refresh();
     context.registerBean("user1",User.class,() -> new User());
     //3 Obtenir à spring Objet enregistré
     // User user = (User)context.getBean("com.igeek.spring5.test.User");
     User user = (User)context.getBean("user1");
     System.out.println(user);
}

4.Spring5Soutien à la consolidationJUnit5

4.1 Spring5IntégrationJUnit4

Première étape Modifierpom.xml,Ajouterspring-testDépendance

<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.3.4</version>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

Deuxième étape Créer une classe de test,Compléter par annotation

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

//JUnit4Version
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring.xml")
public class JTest4 {
    
    
}

4.2 Spring5IntégrationJUnit5

Première étape Modifierpom.xml,AjouterJUnit5Dépendance

<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.7.0</version>
</dependency>

Deuxième étape Créer une classe de test,Compléter avec des annotations

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

//JUnit5Version
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:spring.xml")
public class JTest5 {
    
}

4.3 Compléter la consolidation en remplaçant les deux annotations ci - dessus par une annotation composée

Les annotations combinées peuvent être utilisées @SpringJUnitConfig

import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

//JUnit5Version
@SpringJUnitConfig(locations = "classpath:spring.xml")
public class JTest5 {
    

}

版权声明
本文为[Vers le Haut]所创,转载请带上原文链接,感谢
https://cdmana.com/2022/01/202201080601055993.html

Tags printemps
Scroll to Top