Résumé et examen des notes d'étude de printemps (Crazy God said java)

Notes d'étude de printemps

1. Printemps

1.1 Introduction

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>

1.2 Composition

insérez la description de l'image ici

1.3 Avantages

● Conception non intrusive

Spring est un framework non invasif qui minimise la dépendance du code d'application vis-à-vis du framework.
● Découplage pratique et développement simplifié

Spring est une grande usine, qui peut confier la création de tous les objets et la maintenance des dépendances à la gestion des conteneurs Spring, ce qui réduit considérablement le couplage entre les composants.
● Prise en charge de l'AOP

Spring prend en charge AOP, qui permet le traitement centralisé de certaines tâches courantes, telles que la sécurité, les transactions, les journaux, etc., améliorant ainsi la réutilisabilité des programmes.
● Prend en charge le traitement déclaratif des transactions

La gestion des transactions ne peut être complétée que par configuration, sans programmation manuelle.
● Test de programme pratique

Spring prend en charge Junit4, qui peut facilement tester les programmes Spring via des annotations.
● Réduire la difficulté d'utilisation de l'API Java EE

Spring fournit des packages pour certaines API très difficiles à utiliser dans le développement Java EE (telles que : JDBC, JavaMail, etc.), ce qui réduit considérablement la difficulté d'application de ces API.

Deux caractéristiques majeures de Spirng

  • Inversion de contrôle (IOC), programmation orientée aspect (AOP)

2.CIO

1. Interface utilisateur Dao

public interface UserDao {
    
    
    void getUser();
}

2. Classe d'implémentation UserDaoImpl

public class UserDaoImpl implements UserDao {
    
    
    public void getUser() {
    
    
        System.out.println("默认获取用户数据");
    }
}

3. Interface métier UserService

public interface UserService {
    
    
    void getUser();
}

4. Classe d'implémentation métier UserServiceImpl

public class UserServiceImpl implements UserService {
    
    

    private UserDao userDao = new UserDaoImpl();

    public void getUser() {
    
    
        userDao.getUser();
    }
}

5. Testez

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

        //用户实际调用的是业务层,dao层他们不需要接触!
        UserService userService = new UserServiceImpl();
        userService.getUser();
    }
}

insérez la description de l'image ici
Ici, l'injection d'ensemble est utilisée pour changer l'initiative du programme d'origine du programmeur à l'utilisateur. Les utilisateurs peuvent appeler la méthode de leur choix, ce qui réduit considérablement la pression exercée sur les programmeurs pour modifier le code.

    private UserDao userDao;

    //利用set进行动态实现值的注入!
    public void setUserDao(UserDao userDao) {
    
    
        this.userDao = userDao;
    }

Essence du CIO

L'inversion de contrôle (IOC) est une idée de conception et l'injection de dépendance DI est une méthode pour réaliser l'IOC. Sans IOC, nous utilisons la programmation orientée objet. La création d'objets est contrôlée par le programme, c'est-à-dire nos programmeurs. Après avoir utilisé IOC, l'initiative de création d'objet est inversée.
Via xml ou des annotations, pour obtenir le moyen de générer un objet spécifique, le conteneur IOC est utilisé pour implémenter l'inversion de contrôle dans Spring, et la méthode d'implémentation est DI.

3.Bonjour le monde

Construisez simplement un projet maven

Classe d'entité

public class Hello {
    
    
    private String str;

    public String getStr() {
    
    
        return str;
    }

    public void setStr(String str) {
    
    
        this.str = str;
    }

    @Override
    public String toString() {
    
    
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--使用Spring来创建对象,在Spring这些都称为Bean
    类型 变量名 = new 类型();
    Hello hello = new Hello();

    id = 变量名
    class = new的对象
    property 相当于给对象中的属性设置一个值!
        -->
    <bean id="hello" class="com.kuang.pojo.Hello">
        <property name="str" value="Spring"/>
    </bean>
</beans>

dernier test

public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        //获取Spring的上下文对象!
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //我们的对象现在都在Spring中的管理了,我们需要使用,直接去里面取出来就可以!
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}
  • À ce stade, l'objet est créé par le conteneur Spring et ses propriétés sont également définies par Spring.
    Ce processus est une inversion de contrôle !

4. IOC crée des objets

Au moment où le xml ou d'autres fichiers de configuration sont chargés, l'objet a déjà été initialisé.
Par défaut, Spring crée des objets en utilisant la construction sans argument. Bien sûr, nous pouvons également utiliser la construction de paramètres pour créer des objets.
1. Affectation d'indice

<!--第一种方式:下标赋值    -->
<bean id="user" class="com.kuang.pojo.User">
    <constructor-arg index="0" value="狂神说Java"/>
</bean>

2. Type (non recommandé)

<!--第二种方式:通过类型的创建,不建议使用    -->
<bean id="user" class="com.kuang.pojo.User">
    <constructor-arg type="java.lang.String" value="lifa"/>
</bean>

3. Nom du paramètre

<!--第三种方式:直接通过参数名来设置    -->
<bean id="user" class="com.kuang.pojo.User">
    <constructor-arg name="name" value="李发"/>
</bean>

5. Configuration du ressort

5.1 Alias

Si un alias est ajouté, nous pouvons également utiliser l'alias pour obtenir cet objet.

    <alias name="user" alias="userNew"/>

Afin de rendre le code plus concis ou de réduire la quantité de code.

5.2 Configuration des beans

  • id : l'identifiant unique du bean, qui équivaut à notre nom d'objet

  • class : nom complet correspondant à l'objet bean : nom du package + nom de la classe

  • name : c'est aussi un alias, et name peut prendre plusieurs alias en même temps

    <bean id="userT" class="com.kuang.pojo.UserT" name="user2 u2,u3;u4">
        <property name="name" value="黑心白莲"/>
    </bean>

5.3importer des fichiers fusionnés

Généralement utilisé pour le développement d'équipe, il peut importer et fusionner plusieurs fichiers de configuration en un seul.
Zhang San développe un xml, Li Si développe un xml, Wang Wu développe un xml, et finalement crée une application.xml et utilise import pour importer et fusionner en un xml.
Je n'écrirai pas de code ici, comprenez-le simplement.

6. Injection de dépendance

6.1 Injection de constructeur

Aucune construction de paramètre (printemps par défaut) et la construction de paramètre, comme mentionné précédemment, ne sera répétée ici.

6.2 Définir l'injection de la méthode ···Points clés···

  • Injection de dépendance : Set Injection
  • Toutes les valeurs d'attributs de l'objet sont injectées par le conteneur spring !
    【Construction de l'environnement】
    1. Type complexe
public class Address {
    
    
    private String address;

    public String getAddress() {
    
    
        return address;
    }

    public void setAddress(String address) {
    
    
        this.address = address;
    }
}

2. Objet à tester

public class Student {
    
    

    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
}

3、beans.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="student" class="com.kuang.pojo.Student">
        <!--第一种:普通值注入,value        -->
        <property name="name" value="黑心白莲"/>
    </bean>
</beans>

4. Testez

public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        Student student = (Student) context.getBean("student");
        System.out.println(student.getName());
    }
}

5. Complétez enfin les informations

    <bean id="address" class="com.kuang.pojo.Address">
        <property name="address" value="西安"/>
    </bean>

    <bean id="student" class="com.kuang.pojo.Student">
        <!--第一种:普通值注入,value        -->
        <property name="name" value="黑心白莲"/>

        <!--第二种:        -->
        <property name="address" ref="address"/>

        <!--数组        -->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
        </property>

        <!--List        -->
        <property name="hobbies">
            <list>
                <value>打篮球</value>
                <value>看电影</value>
                <value>敲代码</value>
            </list>
        </property>

        <!--Map        -->
        <property name="card">
            <map>
                <entry key="身份证" value="123456789987456321"/>
                <entry key="银行卡" value="359419496419481649"/>
            </map>
        </property>

        <!--Set        -->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>COC</value>
                <value>BOB</value>
            </set>
        </property>

        <!--NULL        -->
        <property name="wife">
            <null/>
        </property>

        <!--Properties        -->
        <property name="info">
            <props>
                <prop key="driver">20191029</prop>
                <prop key="url">102.0913.524.4585</prop>
                <prop key="user">黑心白莲</prop>
                <prop key="password">123456</prop>
            </props>
        </property>

    </bean>

Les espaces de noms p et c peuvent également être injectés,
nécessitant des contraintes d'importation

       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--p命名空间注入,可以直接注入属性的值:property-->
    <bean id="user" class="com.kuang.pojo.User" p:name="黑心白莲" p:age="20"/>

    <!--c命名空间注入,通过构造器注入:constructor-args-->
    <bean id="user2" class="com.kuang.pojo.User" c:name="狂神" c:age="22"/>
</beans>

6.3 Portée des haricots

  • mode singleton (par défaut)
<bean id="user2" class="com.kuang.pojo.User" c:name="狂神" c:age="22" scope="singleton"/>
  • Mode prototype : Chaque fois que vous sortez du conteneur, un nouvel objet sera généré !
<bean id="user2" class="com.kuang.pojo.User" c:name="狂神" c:age="22" scope="prototype"/>

7. Méthode d'assemblage automatique (haricot)

  • Spring le recherchera automatiquement dans le contexte et assemblera automatiquement les propriétés du bean !
    1. Configuration explicite en xml ;
    2. Configuration explicite en java ;
    3. Bean d'assemblage automatique implicite **

7.1 Essais

Créez de nouveaux modules, une personne et deux animaux !

    <bean id="cat" class="com.kuang.pojo.Cat"/>
    <bean id="dog" class="com.kuang.pojo.Dog"/>

    <bean id="people" class="com.kuang.pojo.People">
        <property name="name" value="小白莲"/>
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
    </bean>

7.2 Surnoms

  • byName : il recherchera automatiquement dans le contexte du conteneur, et l'identifiant du bean correspondant à la valeur derrière la méthode set de son propre objet !
        <bean id="people" class="com.kuang.pojo.People" autowire="byName">
            <property name="name" value="小白莲"/>
        </bean>

7.3 Par type

  • byType : il trouvera automatiquement les beans du même type que ses propres propriétés d'objet dans le contexte du conteneur !
        <bean id="people" class="com.kuang.pojo.People" autowire="byType">
            <property name="name" value="小白莲"/>
        </bean>

Avis:

  • Lorsque ByName, vous devez vous assurer que l'identifiant de tous les beans est unique, et ce bean doit être cohérent avec la valeur de la méthode set de la propriété injectée automatiquement !

  • Lorsque ByType, il est nécessaire de s'assurer que la classe de tous les beans est unique, et ce bean doit être cohérent avec le type de la propriété automatiquement injectée !

7.4 Mise en œuvre à l'aide d'annotations

Spring2.5 et supérieur prennent en charge les annotations, et jdk1.5 et supérieur prennent en charge les annotations !
1. Contraintes d'importation
2. Prise en charge des annotations de configuration

<?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
	        https://www.springframework.org/schema/beans/spring-beans.xsd
	        http://www.springframework.org/schema/context
	        https://www.springframework.org/schema/context/spring-context.xsd">
		
		<!--开启注解的支持    -->
        <context:annotation-config/>
</beans>

@Autowired
peut être utilisé directement sur la propriété ! Peut également être utilisé sur des méthodes fixes !

test

public class People {
    
    
    //如果显式定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
    @Autowired(required = false)
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;
}

Lorsque l'assemblage automatique ne peut pas être terminé, utilisez @Qualifier(value = "xxx") pour configurer l'utilisation de @Autowired et spécifiez un objet bean unique à injecter !

public class People {
    
    
    @Autowired
    @Qualifier(value = "cat111")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog222")
    private Dog dog;
    private String name;
}

@Ressource

public class People {
    
    

    @Resource
    private Cat cat;

    @Resource
    private Dog dog;
}

La différence entre @Resource et @Autowired :

  • Les deux sont utilisés pour l'assemblage automatique et peuvent être placés sur le champ d'attribut

  • @Autowired est implémenté par byType, et cet objet doit obligatoirement exister ! [couramment utilisé]

  • @Resource est réalisé par byName par défaut, si le nom est introuvable, il est réalisé par byType ! Si aucun d'entre eux ne peut être trouvé, signalez une erreur ! [couramment utilisé]

  • L'ordre d'exécution est différent : @Autowired est implémenté par byType.

8. Développement d'annotations

Après Spring4, le développement d'annotations est essentiellement utilisé.
L'utilisation des annotations nécessite l'import de contraintes et le support des annotations de configuration !

	<?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
		        https://www.springframework.org/schema/beans/spring-beans.xsd
		        http://www.springframework.org/schema/context
		        https://www.springframework.org/schema/context/spring-context.xsd">
			
			<!--开启注解的支持    -->
	        <context:annotation-config/>
	</beans>

Comment les propriétés du haricot sont injectées

//等价于<bean id="user" class="com.kuang.pojo.User"/>
//@Component 组件

@Component
public class User {
    
    

    //相当于  <property name="name" value="白莲"/>
    @Value("白莲")
    public String name;
}

annotation dérivée

  • @Composant
  • dao 【@Repository】
  • service 【@Service】
  • controller [@Controller]
    a la même fonction, enregistrer une classe dans Spring et assembler des beans pour
    un assemblage automatique
  • @Autowired : Autowire par type, nom. Si Autowired ne peut pas assembler automatiquement l'attribut de manière unique, il doit être configuré via @Qualifier(value = "xxx").
  • Le champ @Nullable marque cette annotation, indiquant que ce champ peut être nul ;
  • @Resource : Câblage automatique par nom, type.
    La différence entre xml et les annotations
    xml est utilisé pour gérer les beans ;
    les annotations ne sont chargées que de compléter l'injection d'attributs ;
    xml est plus polyvalent et convient à toutes les occasions ! Maintenance simple et pratique
    Si les annotations prennent effet, vous devez activer la prise en charge des annotations !
    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.kuang"/>
    <!--开启注解的支持    -->
    <context:annotation-config/>

9. Façon Java de configurer Spring

A partir de maintenant, n'utilisez pas la configuration xml de Spring et laissez-la à java !

Classe d'entité

//这里这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中
@Component
public class User {
    
    
    private String name;

    public String getName() {
    
    
        return name;
    }

    @Value("黑心白莲") //属性注入值
    public void setName(String name) {
    
    
        this.name = name;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

fichier de configuration

// 这个也会Spring容器托管,注册到容器中,因为它本来就是一个@Component
// @Configuration代表这是一个配置类,就和我们之前看的beans.xml
@Configuration
@ComponentScan("com.kuang.pojo")
@Import(KuangConfig2.class)
public class KuangConfig {
    
    

    // 注册一个bean,就相当于我们之前写的一个bean标签
    // 这个方法的名字,就相当于bean标签中id属性
    // 这个方法的返回值,就相当于bean标签中的class属性
    @Bean
    public User user(){
    
    
        return new User(); // 就是返回要注入到bean的对象!
    }
}

test

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

        //如果完全使用了配置类方式去做,我们就只能通过 AnnotationConfig 上下文来获取容器,通过配置类的class对象加载!
        ApplicationContext context = new AnnotationConfigApplicationContext(KuangConfig.class);

        User user = context.getBean("user", User.class);
        System.out.println(user.getName());
    }
}

Cette méthode est souvent utilisée dans springboot !

10. Mode mandataire

Le mode proxy est le principe sous-jacent d'aop!
insérez la description de l'image ici

10.1 Proxy statique

  • Rôle abstrait : généralement, les interfaces ou les classes abstraites sont utilisées pour résoudre
  • Rôle réel : Rôle par procuration
  • Rôle d'acteur : Agissant comme un vrai personnage, après avoir agi comme un vrai personnage, nous faisons généralement quelques opérations auxiliaires
  • client : la personne qui accède à l'objet proxy !
    rôle abstrait
//租房
public interface Rent {
    
    
    public void rent();
}

vrai rôle

//房东
public class Host implements Rent{
    
    
    public void rent() {
    
    
        System.out.println("房东出租房子!");
    }
}

rôle d'agent

public class Proxy implements Rent{
    
    
    private Host host;

    public Proxy() {
    
    
    }

    public Proxy(Host host) {
    
    
        this.host = host;
    }

    public void rent() {
    
    
        host.rent();
        seeHouse();
        sign();
        fee();
    }

    //看房
    public void seeHouse(){
    
    
        System.out.println("中介带着看房子!");
    }

    //签合同
    public void sign(){
    
    
        System.out.println("和中介签署租赁合同!");
    }

    //收费用
    public void fee(){
    
    
        System.out.println("中介收取费用!");
    }
}

Rôle de courtier d'accès client

public class Client {
    
    
    public static void main(String[] args) {
    
    
        //房东要出租房子
        Host host = new Host();
//        host.rent();

        //代理,中介帮房东出租房子,并且代理角色一般会有一些附属操作!
        Proxy proxy = new Proxy(host);

        //不用面对房东,直接找中介租房即可!
        proxy.rent();
    }
}
  • Peut rendre le fonctionnement de vrais personnages plus pur! Pas besoin de prêter attention à certaines affaires publiques

  • Le rôle public est remis au rôle de mandataire ! La division du travail est réalisée !

  • Quand l'entreprise publique s'agrandit, c'est propice à une gestion centralisée !
    Cependant, la quantité de code doublera et l'efficacité du développement deviendra plus faible !

10.2 Approfondir la compréhension

rôle abstrait

public interface UserService {
    
    
    public void add();
    public void delete();
    public void update();
    public void query();
}

vrai rôle

//真实角色
public class UserServiceImpl implements UserService{
    
    
    public void add() {
    
    
        System.out.println("增加了一个用户!");
    }

    public void delete() {
    
    
        System.out.println("删除了一个用户!");
    }

    public void update() {
    
    
        System.out.println("修改了一个用户!");
    }

    public void query() {
    
    
        System.out.println("查询了一个用户!");
    }
}

rôle d'agent

public class UserServiceProxy implements UserService{
    
    
    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
    
    
        this.userService = userService;
    }

    public void add() {
    
    
        log("add");
        userService.add();
    }

    public void delete() {
    
    
        log("delete");
        userService.delete();
    }

    public void update() {
    
    
        log("update");
        userService.update();
    }

    public void query() {
    
    
        log("query");
        userService.query();
    }

    public void log(String msg){
    
    
        System.out.println("[Debug] 使用了一个"+msg+"方法");
    }
}

Rôle de courtier d'accès client

public class Client {
    
    
    public static void main(String[] args) {
    
    
        UserServiceImpl userService = new UserServiceImpl();

        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);

        proxy.delete();
    }
}

10.3 Proxy dynamique

  • Sa classe proxy est générée dynamiquement
  • Il peut être divisé en deux catégories :
    1. Basé sur l'interface - proxy dynamique JDK
    2. Basé sur les classes : cglib
    3. Implémentation du bytecode Java : javassist
    ici pour en savoir plus sur la classe proxy (Proxy) à l'avance ; gestionnaire d'appels (invocationHandler)
    abstract rôle
public interface Rent {
    
    
    public void rent();
}

** Vrai personnage

public class Host implements Rent{
    
    
    public void rent() {
    
    
        System.out.println("房东要出租房子!");
    }
}

Classe ProxyInvocationHandlerProxyInvocationHandler class

//我们会用这个类,自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {
    
    
    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
    
    
        this.rent = rent;
    }

    //生成得到代理类
    public Object getProxy(){
    
    
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                rent.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        //动态代理的本质,就是使用反射机制实现!
        Object result = method.invoke(rent, args);
        seeHose();
        fee();
        return result;
    }

    public void seeHose(){
    
    
        System.out.println("中介带着看房子!");
    }

    public void fee(){
    
    
        System.out.println("中介收取费用!");
    }
}

test

public class Client {
    
    
    public static void main(String[] args) {
    
    
        //真实角色
        Host host = new Host();

        //代理角色:现在没有
        ProxyInvocationHandler pih = new ProxyInvocationHandler();

        //通过调用程序处理角色来处理我们要调用的接口对象!
        pih.setRent(host);
        Rent proxy = (Rent) pih.getProxy(); //这里的proxy就是动态生成的,我们并没有写
        proxy.rent();

    }
}

Proposez ProxyInvocationHandler en tant que classe d'outils

//用这个类自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {
    
    

    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
    
    
        this.target = target;
    }

    //生成得到代理类
    public Object getProxy(){
    
    
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }

    public void log(String msg){
    
    
        System.out.println("[Debug] 使用了一个"+msg+"方法");
    }
}

Avantages des proxys dynamiques :

  • Peut rendre le fonctionnement de vrais personnages plus pur! Pas besoin de prêter attention à certaines affaires publiques
  • Le rôle public est remis au rôle de mandataire ! La division du travail est réalisée !
  • Quand l'entreprise publique s'agrandit, c'est propice à une gestion centralisée !
  • Une classe de proxy dynamique proxy une interface, qui correspond généralement à un type d'entreprise
  • Une classe proxy dynamique peut proxy plusieurs classes, tant que la même interface est implémentée !

11、OPA

11.1 Présentation de l'AOP

AOP (Aspect Oriented Programming) signifie : programmation orientée aspect, une technologie qui réalise une maintenance unifiée des fonctions du programme grâce à la pré-compilation et au proxy dynamique d'exécution.
insérez la description de l'image ici

11.2 Le rôle de l'AOP au printemps

Fournit des transactions déclaratives ; autorise les aspects définis par l'utilisateur

  • Préoccupations transversales : méthodes ou fonctions qui couvrent plusieurs modules d'une application. Autrement dit, la partie qui n'a rien à voir avec notre logique métier, mais à laquelle nous devons prêter attention, est la préoccupation transversale. Tels que la journalisation, la sécurité, la mise en cache, les transactions, etc...
  • ASPECT : Un objet particulier où les préoccupations transversales sont modularisées. C'est-à-dire que c'est une classe.
  • Conseil : Le travail que l'aspect doit accomplir. C'est-à-dire qu'il s'agit d'une méthode dans une classe.
  • Cible : L'objet à notifier.
  • Proxy : un objet créé après l'application d'une notification à un objet cible.
  • PointCut : définition du "lieu" où les conseils d'aspect s'exécutent.
  • Point de connexion (JointPoint) : Le point d'exécution qui correspond au point de coupure.
    insérez la description de l'image ici
    Spring prend en charge 5 types de conseils :
    insérez la description de l'image ici
    aop consiste à ajouter de nouvelles fonctions sans modifier le code d'origine.

11.3 Implémenter AOP avec Spring

Pour utiliser le tissage AOP, vous devez importer un package de dépendances !

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

1. Utilisez l'interface API de Spring [principalement l'implémentation de l'interface API Spring]
sous le package de service, définissez l'interface métier UserService et la classe d'implémentation UserServiceImpl

public interface UserService {
    
    
    public void add();
    public void delete();
    public void update();
    public void select();
}
public class UserServiceImpl implements UserService {
    
    
    public void add() {
    
    
        System.out.println("增加了一个用户!");
    }

    public void delete() {
    
    
        System.out.println("删除了一个用户!");
    }

    public void update() {
    
    
        System.out.println("更新了一个用户!");
    }

    public void select() {
    
    
        System.out.println("查询了一个用户!");
    }
}

Sous le package de journal, définissez notre classe d'amélioration, une pré-amélioration de journal et une classe de post-amélioration AfterLog

public class Log implements MethodBeforeAdvice {
    
    

    //method: 要执行的目标对象的方法
    //args:参数
    //target:目标对象
    public void before(Method method, Object[] agrs, Object target) throws Throwable {
    
    
        System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
    }
}
public class AfterLog implements AfterReturningAdvice {
    
    

    //returnValue: 返回值
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    
    
        System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
    }
}

Enfin, enregistrez-vous dans le fichier spring et implémentez l'implémentation aop cut-in, faites attention aux contraintes d'importation et configurez le fichier applicationContext.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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注册bean-->
    <bean id="userService" class="com.kuang.service.UserServiceImpl"/>
    <bean id="log" class="com.kuang.log.Log"/>
    <bean id="afterLog" class="com.kuang.log.AfterLog"/>

    <!--方式一:使用原生Spring API接口-->
    <!--配置aop:需要导入aop的约束-->
    <aop:config>
        <!--切入点:expression:表达式,execution(要执行的位置!* * * * *)-->
        <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>

        <!--执行环绕增加!-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

</beans>

test

public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        //动态代理代理的是接口:注意点
        UserService userService = (UserService) context.getBean("userService");

        userService.add();
//        userService.select();
    }
}

2. Personnalisez la classe pour implémenter AOP [principalement la définition d'aspect]
définissez votre propre classe de découpe DiyPointCut sous le package diy

public class DiyPointCut {
    
    
    public void before(){
    
    
        System.out.println("======方法执行前======");
    }

    public void after(){
    
    
        System.out.println("======方法执行后======");
    }
}

fichier de configuration

    <!--方式二:自定义类-->
    <bean id="diy" class="com.kuang.diy.DiyPointCut"/>

    <aop:config>
        <!--自定义切面,ref 要引用的类-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

Troisièmement, utilisez des annotations pour réussir !
Classe améliorée AnnotationPointCut définie dans le package diy pour la mise en œuvre des annotations

//声明式事务!
@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
    
    

    @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void before(){
    
    
        System.out.println("====方法执行前====");
    }

    @After("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void after(){
    
    
        System.out.println("====方法执行后====");
    }

    //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点;
    @Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable{
    
    
        System.out.println("环绕前");

        Signature signature = jp.getSignature();// 获得签名
        System.out.println("signature:"+signature);

        Object proceed = jp.proceed(); //执行方法

        System.out.println("环绕后");

        System.out.println(proceed);
    }

}

Dans le fichier de configuration Spring, enregistrez le bean et ajoutez des configurations prenant en charge les annotations.

    <!--方式三:使用注解-->
    <bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut"/>
    <!--开启注解支持! JDK(默认是 proxy-target-class="false")  cglib(proxy-target-class="true"-->
    <aop:aspectj-autoproxy/>

12. Opérations déclaratives

12.1 Examen des transactions

  • Traitez un groupe d'entreprises comme une seule entreprise ; soit elles réussissent toutes, soit elles échouent toutes !

  • Les transactions sont très importantes dans le développement d'un projet, quand il s'agit de cohérence des données, il ne faut pas négliger !

  • Veiller à l'exhaustivité et à la cohérence.
    Principes de transaction ACID :

  • Atomicité

     事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用。
    
  • Cohérence

     一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中。
    
  • isolement

     可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
    
  • Durabilité

     事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中。
    

test:

Copier le code ci-dessus dans un nouveau projet
Dans le cas précédent, nous avons ajouté deux méthodes à l'interface userMapper, supprimer et ajouter des utilisateurs ;
copier le code ci-dessus dans un nouveau projet
Dans le cas précédent, nous avons donné userMapper Ajouté deux méthodes à l'interface, supprimer et ajouter des utilisateurs ;

//添加一个用户
int addUser(User user);

//根据id删除用户
int deleteUser(int id);

Dans le fichier UserMapper, nous avons délibérément mal écrit les suppressions, testez !

<insert id="addUser" parameterType="com.kuang.pojo.User">
insert into user (id,name,pwd) values (#{
    
    id},#{
    
    name},#{
    
    pwd})
</insert>

<delete id="deleteUser" parameterType="int">
deletes from user where id = #{
    
    id}
</delete>

Écrivez la classe d'implémentation UserMapperImpl de l'interface. Dans la classe d'implémentation, nous allons opérer une vague

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
    
    


    //增加一些操作
    public List<User> selectUser() {
    
    
        User user = new User(5, "小王", "185161");
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        mapper.addUser(user);
        mapper.deleteUser(5);

        return mapper.selectUser();
    }
    
    //新增
    public int addUser(User user) {
    
    
        return getSqlSession().getMapper(UserMapper.class).addUser(user);
    }

    //删除
    public int deleteUser(int id) {
    
    
        return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
    }
}

test

    @Test
    public void test(){
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);

        for (User user : userMapper.selectUser()) {
    
    
            System.out.println(user);
        }
    }

Erreur : exception sql, la suppression est mal écrite

Résultat : Le résultat de la base de données indique que l'insertion a réussi !

Il n'y a pas de gestion des transactions, nous voulons qu'ils réussissent tous pour réussir, et si l'un échoue, ils échouent tous, il faudrait des transactions !

Dans le passé, nous devions tous gérer manuellement les affaires par nous-mêmes, ce qui était très gênant !

Mais Spring nous fournit une gestion des transactions, nous n'avons qu'à configurer ;

12.2 Gestion des transactions au printemps

gestion programmatique des transactions

  • Intégrer le code de gestion des transactions dans les méthodes commerciales pour contrôler la validation et l'annulation des transactions
  • Inconvénient : un code de gestion de transaction supplémentaire doit être inclus dans la logique métier de chaque opération de transaction
    Gestion déclarative des transactions
  • Généralement plus facile à utiliser que les transactions programmatiques.
  • Séparez le code de gestion des transactions des méthodes commerciales et implémentez la gestion des transactions de manière déclarative.
  • Considérez la gestion des transactions comme une préoccupation transversale et modularisez-la grâce à la méthode AOP. Spring prend en charge la gestion déclarative des transactions via le framework Spring AOP.
    Utilisez Spring pour gérer les transactions, faites attention à la contrainte d'import du fichier d'en-tête : tx
xmlns:tx="http://www.springframework.org/schema/tx"

http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

Transaction JDBC

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

Après avoir configuré le gestionnaire de transactions, nous devons configurer les notifications de transaction

    <!--结合AOP实现事务的织入-->
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--给那些方法配置事务-->
        <!--配置事务的传播特性: new -->
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

Fonctionnalités de propagation des transactions Spring :
le comportement de propagation des transactions est la manière dont les transactions se propagent entre ces méthodes lorsque plusieurs méthodes de transaction s'appellent. Spring prend en charge 7 comportements de propagation des transactions :

  • propagation_requierd : s'il n'y a pas de transaction actuellement, créez une nouvelle transaction. S'il existe déjà une transaction, rejoignez cette transaction. C'est le choix le plus courant.
  • propagation_supports : prend en charge la transaction en cours, s'il n'y a pas de transaction en cours, elle sera exécutée dans une méthode non transactionnelle.
  • propagation_mandatory : utilise la transaction en cours et lève une exception s'il n'y a pas de transaction en cours.
  • propagation_required_new : crée une nouvelle transaction, s'il y a une transaction en cours, suspend la transaction en cours.
  • propagation_not_supported : exécute les opérations de manière non transactionnelle. S'il existe une transaction en cours, suspend la transaction en cours.
  • propagation_never : effectue l'opération de manière non transactionnelle, en levant une exception si la transaction en cours existe.
  • propagation_nested : exécution dans une transaction imbriquée s'il existe une transaction en cours. S'il n'y a pas de transaction actuellement, effectuez une opération similaire à propagation_required.
    Le comportement de propagation de transaction par défaut de Spring est PROPAGATION_REQUIRED, qui convient à la plupart des situations.
    Configurer AOP, importer le fichier d'en-tête d'aop
    <!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

Supprimez les données que vous venez d'insérer et testez à nouveau !

    @Test
    public void test(){
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);

        for (User user : userMapper.selectUser()) {
    
    
            System.out.println(user);
        }
    }

Pourquoi avez-vous besoin de transactions ?

  • Si vous ne configurez pas les transactions, il peut y avoir des incohérences dans la soumission des données ;

  • Si nous ne configurons pas les transactions déclaratives dans Spring, nous devons configurer manuellement les transactions dans le code !

  • Les transactions sont très importantes dans le développement du projet, ce qui implique des problèmes de cohérence et d'intégrité des données, et ne doit pas être bâclé !
    Les vidéos du professeur Kuangshen sont vraiment très appropriées pour que le public puisse apprendre, et j'ai beaucoup gagné en regardant et en apprenant. Suivons la vidéo de M. Kuangshen et applaudissons ensemble ! Programmeur!

Je suppose que tu aimes

Origine blog.csdn.net/lj20020302/article/details/129300548
conseillé
Classement