Notas de estudio de Sping (con ejemplos, súper detalladas)

Tabla de contenido

1. Hablemos primero de lo que es la primavera

1.1 Las dependencias que deben importarse para escribir código Spring: (que contiene muchos paquetes jar)

 2. Derivación teórica de inversión de control (IOC)

2.1 Obtener el objeto de contexto de Spring en Test

2.2 Inyección de dependencia

2.3 Extensión: inyección de etiquetas C y etiquetas P

3. Inversión de Control

4. La forma en que IOC crea objetos

4.1 Asignación de subíndice, pero necesita crear un constructor con parámetros

4.2 La creación por tipo está en desuso

4.3 Establecer directamente a través de parámetros

5. Grupo de conexiones de base de datos

6. Ámbito de aplicación

6.1 Modo Singleton: (mecanismo predeterminado de resorte)

6.2 Patrón prototipo

6.3 Otras solicitudes, sesiones, aplicaciones

7. Montaje automático de frijol

7.1 Uso de anotaciones para realizar un ensamblaje automático

7.1.1@Autocableado

7.1.2 Restricciones de importación

7.1.3 Implementación de frijoles

7.1.4 Inyección de propiedad

7.2 Soporte de anotaciones de configuración

7.2.1 Diferencia entre @Autowired y @Resource

7.3 Comparación de XML y anotaciones

8. Modo proxy

8.1 Para qué se utiliza AOP

8.2 Proxy estático

8.3 Comprensión profunda del proxy estático

9. Proxy dinámico

9.1 Ejemplo

9.2 Comprensión más profunda de los proxies dinámicos

9.3 Resumen del Modo Proxy

10. Comprender la reflexión

11.AOP

11.1 ¿Qué es AOP?

11.2 El papel de Aop en Spring 

 11.2.1 Dos métodos proxy de Spring AOP

11.3 Comience con el tema, primero guíe el paquete

11.4 Específicamente dividido en tres formas

11.4.1 La primera forma: usar la interfaz SpringAPI original

11.4.2 Método 2: personalizar la clase para implementar Aop

11.4.3 Método 3 Usar anotaciones para implementar

11.5 Resumen de AOP "Heart Bleeding"

12. Transacciones declarativas 

12.1 Cuatro atributos de las transacciones

12.2 Gestión de transacciones en Spring 

12.2.1 Administrador de transacciones 

12.3 Funciones de propagación de transacciones de Spring 

12.4 Importación restringida de archivos de encabezado 

12.5 Caso 

13. Auto-resumen periódico


1. Hablemos primero de lo que es la primavera


    1.Spirng es un contenedor gratuito de código abierto (marco);
    2.Spring es un marco ligero y no invasivo;
    3. Inversión de control (IOC), Programación orientada a aspectos (AOP);
    4. Admite procesamiento de transacciones, admite integración marco!



1.1 Las dependencias que deben importarse para escribir código Spring: (que contiene muchos paquetes jar)

地址:<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>6.0.2</version>
</dependency>

 
2. Derivación teórica de inversión de control (IOC)

  • En esencia, resuelve la necesidad de los programadores de gestionar la creación de objetos , y reduce el acoplamiento del sistema .
  • El programa proporciona pasivamente la interfaz, y la iniciativa está en manos del usuario. Solo necesita obtener la operación del usuario y luego llamar al método correspondiente.
  • La inversión de control es una forma de generar u obtener objetos específicos a través de la descripción (xml o anotación) ya través de un tercero.
  • Es el contenedor IOC que implementa la inversión de control en Spring, y su método de implementación es la inyección de dependencia (DI)

2.1 Obtener el objeto de contexto de Spring en Test

ApplicationContext context = new ClassPathXmlApplicationContext("xml文件");

        Luego ve a .consigue a quien necesites

2.2 Inyección de dependencia

Ejemplo:

public class Address {
    private String address;

    public String getAddress() {
        return address;
    }

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

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}
//对应不同的注入方式
public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address.toString() +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

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

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobbys() {
        return hobbys;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }
}

frijoles.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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <bean id="address" class="com.gcx.pojo.Address">
        <property name="address" value="青岛"/>
    </bean>
    <bean id="student" class="com.gcx.pojo.Student">
<!--        第一种普通值注入 value-->
        <property name="name" value="gcx"/>
<!--        第二种注入bean注入, ref-->
        <property name="address" ref="address"/>
<!--        数组注入-->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
        </property>
<!--        List-->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>看电影</value>
                <value>玩游戏</value>
            </list>
        </property>
<!--        map-->
        <property name="card">
            <map>
                <entry key="身份证" value="111111111111111111"/>
                <entry key="银行卡" value="684546554466455545"/>
            </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="studyId">78945621</prop>
                <prop key="phone">20221206</prop>
                <prop key="姓名">小明</prop>
            </props>
        </property>
    </bean>


</beans>

 Prueba prueba

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.toString());
    }

2.3 Extensión: inyección de etiquetas C y etiquetas P

public class User {
    private String name;
    private int age;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

UserBean.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:util="http://www.springframework.org/schema/util"
       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 http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!--需要先导入约束(第4 5行)-->
    <!--    P命名空间注入-->
    <bean id="User" class="com.gcx.pojo.User" p:name="gcx" p:age="18"/>
<!--C命名空间注入 通过有参无参注入-->
    <bean id="user2" class="com.gcx.pojo.User" c:age="18" c:name="cxg"/>
</beans>

Prueba prueba:

@Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("UserBean.xml");
        User user = (User) context.getBean("user2");//测试P标签对应beanid为user
        System.out.println(user);
    }


3. Inversión de Control


    Control: quien controla la creación de objetos, los objetos de las aplicaciones tradicionales son creados por el propio programa, después de usar Spring, los objetos son creados por Spring Inversión: el programa en sí no crea objetos, sino que se convierte en un objeto receptor pasivo
    .
    Inyección de dependencia: Es usar el método set para inyectar.IOC
    es una idea de programación, que cambia de programación activa a recepción pasiva.


Para lograr diferentes operaciones, solo necesita modificarlo en el archivo de configuración XML.El llamado IOC significa que el objeto es creado, administrado y ensamblado por Spring. 

4. La forma en que IOC crea objetos


Usar constructor sin argumentos

<property name="name" value="123"/>


4.1 Asignación de subíndice, pero necesita crear un constructor con parámetros
 

<constructor-arg index="0" value="456"/>


4.2 La creación por tipo está en desuso

<constructor-arg type="java.lang.String" value="gcx"/>


4.3 Establecer directamente a través de parámetros

<bean id="user" class="com.gcx.User">
        <constructor-arg name="name" value="gcx"/>
</bean>

5. Grupo de conexiones de base de datos


Tecnología de agrupación: prepare algunos recursos previos y vincúlelos a las
conexiones preparadas previamente cuando venga. Número mínimo de conexiones: configúrelo de acuerdo con el número de conexiones de uso común.
Número máximo de conexiones: establezca el número máximo de conexiones. Cuando el número de conexiones excede el número máximo de conexiones, esperará en línea
Tiempo de espera de espera: cuando el tiempo de espera excede el tiempo de espera en cola, automáticamente saldrá del tiempo de espera y generará un error

Escriba un grupo de conexiones e implemente una interfaz Fuente de datos
grupo de datos comunes:

  • DBCP (paquete jar de importación)
  • c3p0 (paquete jar de importación)
  • Druida: Alibaba

Después de usar estos grupos de conexiones de bases de datos, no es necesario escribir el código de la base de datos;
no importa qué fuente de datos se use, la esencia es la misma: la interfaz de la fuente de datos no cambiará y el método no cambiará

6. Ámbito de aplicación


6.1 Modo Singleton: (mecanismo predeterminado de resorte)

<!--<bean id="accountService" class="com.something.DefaultAccountService"/>
(singleton scope is the default) -->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>


6.2 Patrón prototipo

Desventaja: ¡Cada vez que salga del contenedor, se generará un nuevo objeto (desperdiciando recursos)!
 

<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>


6.3 Otras solicitudes, sesiones, aplicaciones

这些只能在web开发中使用到。
官网原话: los ámbitos de solicitud, sesión, aplicación y websocket están disponibles solo si usa una implementación Spring ApplicationContext compatible con la web (como XmlWebApplicationContext). 
Si utiliza estos ámbitos con contenedores Spring IoC regulares, 
como ClassPathXmlApplicationContext,  se genera
una IllegalStateException que se queja de un ámbito de bean desconocido .

7. Montaje automático de frijol


Tres métodos de montaje automático:

                                  1. Configuración de visualización en xml
                                  2. Configuración de visualización en java
                                  3. Bean de ensamblado automático implícito [importante] (byName, byType)


7.1 Uso de anotaciones para realizar un ensamblaje automático

1. El paquete jar de aop debe importarse (consulte el complemento maven)

2. @Autowired (comúnmente utilizado), @Resource

7.1.1@Autocableado

Ejemplo:

public class Cat {
    public void shout(){
        System.out.println("miao");
    }
}
public class Dog {
    public void shout(){
        System.out.println("wang");
    }
}
public class People {
//    如果显示定义了Autowired属性的required为false,说明这个属性可以为null,否则不允许为空;
//    @Autowired(required = false)
    @Autowired
    @Qualifier(value = "cat11")
//    @Qualifier(value = "beanid")当自动装配无法通过一个注解完成时,用来指定一个唯一的bean对象注入
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog11")
    private Dog dog;
    private String name;

    @Override
    public String toString() {
        return "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name='" + name + '\'' +
                '}';
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 beans.xml (no estándar)

<?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/>
<!--    使用Autowired可以不用set方法,前提是自动装配的属性在IOC容器中存在且符合名字byName-->
        <bean id="cat" class="com.gcx.pojo.Cat"/>
        <bean id="cat11" class="com.gcx.pojo.Cat"/>
        <bean id="dog" class="com.gcx.pojo.Dog"/>
        <bean id="dog11" class="com.gcx.pojo.Dog"/>
<!--    自动装配:autowire    byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid(必须对应相同,所有bean的id唯一)
                    byType:会自动在容器上下文中查找,和自己对象属性类型对应相同bean(必须保证所有bean的class全局唯一)-->
    <bean id="people" class="com.gcx.pojo.People">
        <property name="name" value="gcx"/>
<!--        <property name="cat" ref="cat"/>-->
<!--        <property name="dog" ref="dog"/>-->
     </bean>
<!--    开启注解支持-->

</beans>

Prueba prueba

public class Mytest {
    @Test
    public void test(){
        ApplicationContext Context = new ClassPathXmlApplicationContext("beans.xml");
        People people = (People) Context.getBean("people");
        people.getDog().shout();
        people.getCat().shout();
    }
}


7.1.2 Restricciones de importación

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd


7.1.3 Implementación de frijoles


Especifique el paquete de escaneo de anotaciones para configurar qué paquetes se escanean en busca de anotaciones

<context:component-scan base-package="com.gcx"/>


7.1.4 Inyección de propiedad


    (1) No es necesario proporcionar un método de configuración, pero agregue directamente @value("valor");
    (2) Si se proporciona un método de configuración, agregue @value("valor"); al método de configuración;


7.2 Soporte de anotaciones de configuración

<context:annotation-config/> //若使用注解就必须开启,否则注入为空


Si el entorno para el ensamblaje automático de anotaciones @Autowired es más complicado y el ensamblaje automático no se puede completar a través de una anotación [@Autowired], podemos usar @Qualifier(value = "xxx") para configurar el uso de @Autowired y especificar un ¡inyección única de objeto de frijol!


7.2.1 Diferencia entre @Autowired y @Resource


1. Ambos se utilizan para el ensamblaje automático y se pueden colocar en el campo de atributos
2. @Autowired se implementa mediante el método de byType
3. @Resource es el método de byName de forma predeterminada. Si no se puede encontrar el mismo nombre, lo hará ser pasado porEscriba lograr!
Si no se puede encontrar ninguno de ellos, ¡se informará un error!
4. El orden de ejecución es diferente: @Autowired se implementa con el método de byType y @Resource se implementa con el método de byName de forma predeterminada.

7.3 Comparación de XML y anotaciones


1.XML se puede aplicar a cualquier escena, con una estructura clara y fácil mantenimiento
2. Las anotaciones no son proporcionadas por la clase y no se pueden usar, y el desarrollo es simple y conveniente.

Desarrollo integrado de xml y anotaciones: recomiende la mejor práctica xml para administrar beans y deje que las anotaciones completen la inyección de atributos     /**Durante el uso, no se requiere escanear, el escaneo es para anotaciones en clases*/
    

8. Modo proxy

Esta parte necesita comprender primero qué es la reflexión, comprender qué es la reflexión puede ayudar a comprender qué es el modo proxy, consulte el catálogo 10 para obtener más detalles.

[¡El mecanismo subyacente de AOP (Programación Orientada a Aspectos (AOP)) es un proxy dinámico! ]


8.1 Para qué se utiliza AOP

Sin cambiar el código original, se realiza la mejora de la función original, que es la idea central en AOP ;


El modo proxy se divide en:
        1. Proxy estático
        2. Proxy dinámico


Análisis de rol de proxy estático
/**
    * Rol abstracto: generalmente implementado mediante el uso de una interfaz o una clase abstracta (equivalente a un método o comportamiento)
    * Rol real: el rol que se está representando
    * Rol de proxy: actuando como un rol real; rol real, generalmente habrá algunas operaciones integradas.
    * Cliente: use el rol de proxy para realizar algunas operaciones
*/


Ventajas y desventajas de los agentes estáticos
/**
*Ventajas:
* 1. Puede hacer que nuestro papel real sea más puro. Ya no prestamos atención a algunas cosas públicas. *
2. El agente completa los asuntos públicos. Realizó la división del trabajo,
* 3. Cuando el negocio público se expande, se vuelve más centralizado y conveniente
*Desventajas:
*Hay más clases (roles reales) y más clases proxy (roles de agente), el código a escribir se duplica, la carga de trabajo aumenta, y la eficiencia de desarrollo se reduce

8.2 Proxy estático

Ejemplo: [rol real: arrendador; rol abstracto (método): alquilar una casa; rol de agente: intermediario; cliente: persona que compra una casa] para describir todo el agente estático

propietario:

//房东
public class Host implements Rent{

    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }
}

Rentar una casa:

//租房
public interface Rent {
    void rent();
}

intermediario:

//中介
//这里中介去实现了租房子这个方法,就相当于中介帮助房东出租房子
public class ZhongJie implements Rent{
//去找到房东,为了获取房源
    private Host host;

    public ZhongJie() {
    }
//为房东创建实参,为了实现出租房子的方法(行为)
    public ZhongJie(Host host) {
        this.host = host;
    }

    public void rent() {
//通过房东去.出来买房子的方法
        host.rent();
//这是中介(代理对象)自带的一些方法
        seeHouse();//看房子
        hetong();//签合同
        takeMoney();//赚差价
        sell();//卖出房子
    }
/**
*对应的中介自带的方法
*/
//    看房
    public void seeHouse(){
        System.out.println("中介带你看房");
    }
//签合同
    public void hetong(){
        System.out.println("中介签合同");
    }
//赚差价
    public void takeMoney(){
        System.out.println("中介收中介费");
    }
//卖出房子
    public void sell(){
        System.out.println("卖出房子");
    }
}

Quien compra una casa:

public class Empty {
    public static void main(String[] args) {
//        房东要租房子
        Host host = new Host();
//        host.rent();
//        房东去找中介,中介帮房东租房子,但是代理角色一般会有一些自带的操作!
        ZhongJie zhongJie = new ZhongJie(host);
//        有了中介,租房子的人不需要面对房东,直接找中介即可
        zhongJie.rent();
    }
}

resultado de salida:

房东要出租房子
中介带你看房
中介签合同
中介收中介费
卖出房子

Del código anterior, se puede ver fácilmente que el propietario solo proporciona un método (comportamiento) y una lista de la casa que quiero vender; el resto de las otras cosas las proporciona el agente (intermediario) hasta que se vende la casa. lejos;

De igual forma, si se requieren otras operaciones, se pueden implementar directamente en el intermediario.

 8.3 Comprensión profunda del proxy estático

Sin cambiar el código original, se realiza la mejora de la función original

 

ejemplo

//先去写出一些方法
public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}
然后去用实现类实现接口内的方法
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

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

    @Override
    public void update() {
        System.out.println("更改了一个用户");
    }

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

En este punto, si escribes directamente Test test

public class Test {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        userService.add();
    }
}

Parecerá que el resultado es

增加了一个用户

Llamar a otros métodos también es mostrar el contenido de sout, pero en este momento, nuestra querida Parte A ha hecho una solicitud:

Necesito agregar una nueva salida sobre la base de cada salida original, para decirle al usuario qué métodos usamos en segundo plano;

 En primer lugar, nuestro método más directo es escribir otro sout en la clase de implementación para generar los métodos que usamos, pero ¿y si mi método tiene 100? ¿1000? ¿Qué pasa si hay aún más? No puedo agregarlos uno por uno ., por lo que debemos usar nuestro método AOP (programación orientada a aspectos), que es equivalente a configurar un intermediario, primero para obtener nuestro método original y luego para agregar contenido nuevo:

public class UserServiceDaiLi implements UserService{
//获取原有实现类方法
    private UserServiceImpl userservice;
//设置set方法
    public void setUserservice(UserServiceImpl userservice) {
        this.userservice = userservice;
    }
//因为在这里实现了UserService接口,所以去重写(可以不写重写注释,实质上也不算重写)原来内部的信息
    @Override
    public void add() {
        log("add");
        userservice.add();
    }

    @Override
    public void delete() {
        log("delete");
    userservice.delete();
    }

    @Override
    public void update() {
        log("update");
userservice.update();
    }

    @Override
    public void query() {
        log("query");
   userservice.query();
    }
//这里去写我们要新添加的内容,然后在上边的方法中去添加该方法即可达到目的
    public void log(String msg){
//        添加日志
        System.out.println("[Debug]使用了"+msg+"方法");
    }
}

Prueba prueba:

public class Test {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        UserServiceDaiLi DaiLi = new UserServiceDaiLi();
        DaiLi.setUserservice(userService);
//因为要输出的是daili内部新写的内容
        DaiLi.add();

    }
}

La salida es:

[Debug]使用了add方法
增加了一个用户

9. Proxy dinámico

/**Ventajas:
* 1. Puede hacer que nuestro papel real sea más puro. Ya no prestar atención a algunas cosas públicas,
* 2. El negocio público es completado por el agente. La división del trabajo se realiza,
* 3. El público el negocio se expande
* 4. Una clase de proxy dinámico representa una interfaz, que generalmente corresponde a un tipo de negocio. *
5. Una clase de proxy dinámico puede representar múltiples clases, siempre que se implemente la misma interfaz Can. 
*/

---- Esta parte es más abstracta y difícil de entender, cargue directamente el código y la explicación específica está escrita en el código

----En primer lugar, tome los datos del proxy estático como ejemplo

9.1 Ejemplo

propietario:

//房东
public class Host implements Rent {

    @Override
    public void rent() {
        System.out.println("房东要出租房子");
    }
}

Rentar una casa:

//租房
public interface Rent {
    void rent();
}

Objeto proxy (oficialmente ProxyInvocationHandler, llamado DaiLi~~~ para una fácil comprensión):

//使用这个类自动生成代理角色
public class DaiLiInvocationHandler implements InvocationHandler {

//    被代理的接口
    private Rent rent;

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

//    生成得到代理类

    /**
     * @return
     * getClassLoader() 是为了加载类在哪个位置
     * getInterfaces() 表示要代理的接口是哪一个
     * this 代表InvocationHandler本身
     */
     public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
     }

    //(真正的处理是靠invoke方法执行)处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//        动态代理的本质就是使用反射机制实现
        seeHouse();
        Object result = method.invoke(rent,args);
        takeMoney();
        return result;
    }
    public void seeHouse(){
        System.out.println("中介带去看房子");
     }
     public void takeMoney(){
        System.out.println("中介收差价");
     }

}

La persona que vende la casa:

public class Client {
    public static void main(String[] args) {
//        真实角色
        Host host = new Host();
//        代理角色(暂时不存在,需要去调用set设置)
        DaiLiInvocationHandler dih = new DaiLiInvocationHandler();
//        通过调用程序处理角色,来处理我们调用的接口对象!
        dih.setRent(host);
        Rent proxy = (Rent) dih.getProxy();
        proxy.rent();
    }
}

resultado de salida:

中介带去看房子
房东要出租房子
中介收差价

9.2 Comprensión más profunda de los proxies dinámicos

Siguiendo 8.3 para obtener más información sobre el proxy dinámico

Objeto proxy:

//使用这个类自动生成代理角色
public class DaiLiInvocationHandler implements InvocationHandler {
//代理谁:
    //被代理的接口
    private Object target;
//        setter
    public void setTarget(Object target) {
        this.target = target;
    }

    /**
     * @return
     * getClassLoader() 是为了加载类在哪个位置
     * getInterfaces() 表示要代理的接口是哪一个
     * this 代表InvocationHandler本身
     */
//生成得到代理类(固定写法,只需要更改需要实现的接口):
     public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
     }
//调用代理程序的一些方法
    //(真正的处理是靠invoke方法执行)处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //动态代理的本质就是使用反射机制实现
        /**
         * 如果这里的msg去设置单独的一个方法,
         * 那么如果我去调用删除方法,就还要在log内更改为delete
         * 但如果通过invoke的method去.出来getName,则只需要去更改前端的调用方法
         * 后端自动的去动态处理输出的内容
         */
        //        log("add");
        log(method.getName());
        Object result = method.invoke(target,args);
        return result;
    }
//    设置新增日志
    public void log(String msg){
        System.out.println("[Debug]使用了"+msg+"方法");
    }

}

Usuario (persona que alquila una casa):

public class Customer {
    public static void main(String[] args) {
//        真实角色
        UserServiceImpl userService = new UserServiceImpl();
//        代理角色(暂时不存在,需要去设置)
        DaiLiInvocationHandler dih = new DaiLiInvocationHandler();
        dih.setTarget(userService);//设置要代理的对象
        UserService proxy = (UserService) dih.getProxy();
        proxy.delete();
    }
}

resultado de salida:

[Debug]使用了delete方法
删除了一个用户

9.3 Resumen del Modo Proxy

Aquí hay un resumen del modelo de agencia en Zhoumu:

1. En primer lugar, para el problema de "reflexión" del proxy dinámico, primero debe comprender qué es la reflexión y luego mirar el código del modo proxy.

2. En segundo lugar, el modo proxy, como su nombre lo indica, requiere un objeto proxy para ayudar a nuestro código a lograr una división clara del trabajo, de modo que nuestro código no se vea desordenado y todas las operaciones comerciales se entreguen al objeto proxy; nos ayuda en El trabajo de mantenimiento posterior no necesita cambiar nuestro código, lo que viola el principio de apertura y cierre (es decir, las entidades de software deben intentar expandirse sin modificar el código original ).

3. Lo último es comprender la arquitectura (rutinas). Muchas cosas no han cambiado. Solo necesita anotarlas. En el mantenimiento posterior, puede cambiar el contenido especificado para completar el mantenimiento. Comprender objetos reales, objetos proxy, métodos abstractos y llamadas front-end y relación de implementación.

 10. Comprender la reflexión

1. ¿Qué es la reflexión?

En el estado de ejecución, para cualquier clase, se pueden conocer todas las propiedades y métodos de esta clase;

Para cualquier objeto, puede llamar a cualquiera de sus métodos y propiedades

Esta función de obtener información de forma dinámica y llamar a métodos de objetos de forma dinámica se denomina mecanismo de reflexión del lenguaje Java.

2. Ventajas de la reflexión:

Reflection mejora la flexibilidad y la escalabilidad del programa, reduce el acoplamiento y mejora la autoadaptabilidad. Permite que los programas creen y controlen objetos de cualquier clase sin codificar la clase de destino por adelantado.

3. Desventajas de la reflexión

Problemas de rendimiento, el uso de la reflexión es básicamente una operación de interpretación, que es mucho más lenta que el código directo cuando se usa para el acceso a campos y métodos. Por lo tanto, el mecanismo de reflexión se usa principalmente en marcos de sistema que requieren alta flexibilidad y escalabilidad, y no se recomienda para programas ordinarios.

11.AOP

11.1 ¿Qué es AOP?

AOP (Programación Orientada a Aspectos) significa: programación orientada a aspectos, una tecnología que realiza el mantenimiento unificado de las funciones del programa a través de la precompilación y el proxy dinámico en tiempo de ejecución. AOP es una continuación de OOP, un punto caliente en el desarrollo de software, un contenido importante en el marco Spring y un paradigma derivado de la programación funcional. AOP se puede utilizar para aislar varias partes de la lógica comercial, reduciendo así el grado de acoplamiento entre varias partes de la lógica comercial, mejorando la reutilización de los programas y mejorando la eficiencia del desarrollo al mismo tiempo.

11.2 El papel de Aop en Spring 

Términos AOP:

1. Punto de unión

        Un nodo específico en el proceso de ejecución del programa, como una llamada de método o una ejecución de excepción, suele ser una ejecución de método.

2. Corte de punta

        Hace referencia al punto de conexión que debe procesarse. Todas las ejecuciones de métodos son puntos de conexión, y un punto de conexión específico es el punto de entrada (punto de conexión interceptado)

3. Objetivo

        Hace referencia al objeto a notificar, es decir, el objeto de destino del agente;

4. Notificación (consejo)

        También conocida como mejora, es una pieza de código agregada por un aspecto a un punto de conexión específico. En términos simples, la notificación se refiere a qué hacer después del punto de conexión interceptado, por lo que la notificación es la implementación específica del aspecto; la notificación se divide en notificación frontal, notificación posterior, notificación de excepción, notificación final, notificación circundante;

5. Aspecto

        Se refiere a la clase que encapsula el corte horizontal de la función del sistema (como el procesamiento de transacciones), que es la combinación de punto de entrada y notificación;

6. Tejido

        Es el proceso de insertar el código de aspecto en el objeto de destino para generar un objeto proxy;

7. Apoderado

        Significa que después de aplicar la notificación (mejora), se genera un objeto proxy;

 11.2.1 Dos métodos proxy de Spring AOP

Uno es JDK normal y otro es CGLIB.

Cuando el objeto proxy implementa al menos una interfaz, el JDK se usa para crear dinámicamente el objeto proxy de forma predeterminada;

Los métodos CGLIB se utilizan cuando el objeto proxy no implementa ninguna interfaz.

Si se implementa la interfaz, el reparto debe definirse con la interfaz de superclase

Porque no hay muchas cosas que se puedan explicar claramente con palabras en esta parte, así que solo mira los ejemplos.

11.3 Comience con el tema, primero guíe el paquete

<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>

En segundo lugar, cree un archivo de configuración " 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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>

11.4 Específicamente dividido en tres formas

        11.4.1 La primera forma: usar la interfaz SpringAPI original

Primero, escriba la interfaz empresarial y la clase de implementación:

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

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

    @Override
    public void update() {
        System.out.println("更改了一个用户");
    }

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

Luego están las clases mejoradas (pre-notificación y post-notificación)

public class BeforeLog implements MethodBeforeAdvice {
    /**
     *
     * @param method 要执行的目标对象的方法
     * @param args 参数
     * @param target 目标对象
     * @throws Throwable
     */
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(method.getClass().getName()+"的"+method.getName()+"被执行了");
    }
}
public class AfterLog implements AfterReturningAdvice {
    /**
     *
     * @param returnValue 返回值
     * @param method
     * @param args
     * @param target
     * @throws Throwable
     */
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法,返回的结果为"+returnValue);
    }
}

Luego vaya al archivo de configuración de Spring "applicationContext.xml" para registrar el bean y realizar la implementación del corte aop.

<!--    注册bean-->
    <bean id="userService" class="com.gcx.Service.UserServiceImpl"/>
    <bean id="beforeLog" class="com.gcx.log.BeforeLog"/>
    <bean id="afterLog" class="com.gcx.log.AfterLog"/>
    <!--    配置AOP:需要导入aop的约束-->
    <aop:config>
<!--        首先需要一个切入点:expression:表达式,execution(要执行的位置 )-->
<!--        要给com.gcx.Service.UserServiceImpl这个类插入方法,但是这个类有很多方法,所以用.*(..) [两个点代表可以有任意个参数]-->
        <aop:pointcut id="pointcut" expression="execution(* com.gcx.Service.UserServiceImpl.*(..))"/>
<!--    执行环绕增加!-->
        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

Examen final.

public class Mytest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserSerice userService = (UserSerice) context.getBean("userService");
        userService.add();
    }

resultado de salida

java.lang.reflect.Method的add被执行了
增加了一个用户
执行了add方法,返回的结果为null

Se puede ver a partir de esto que, de hecho, ha agregado contenido a mi código original donde quiero agregar contenido, es decir, código mejorado.

11.4.2 Método 2  Clase personalizada para implementar Aop

La clase de implementación empresarial permanece sin cambios, sigue siendo userServiceImpl

Paso 1: escriba una de nuestras propias clases de acceso directo

public class diy {
    public void logBefore(){
        System.out.println("方法执行前");
    }
    public void logAfter(){
        System.out.println("方法执行后");
    }
}

Luego vaya al archivo de configuración de Spring "applicationContext.xml" para registrar el bean. 

    <bean id="diy" class="com.gcx.log.diy"/>
    <aop:config>
<!--        声明为切面(aspect)类-->
        <aop:aspect ref="diy">
<!--            切入点-->
            <aop:pointcut id="pointcut" expression="execution(* com.gcx.Service.UserServiceImpl.*(..))"/>
<!--            通知-->
            <aop:before method="logBefore" pointcut-ref="pointcut" />
            <aop:after method="logAfter" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

prueba

    @Test
    public void LogTest(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserSerice userService = context.getBean("userService", UserSerice.class);
        userService.add();
    }

resultado de salida

方法执行前
增加了一个用户
方法执行后

Así es, incluso si es una clase de corte que personalizamos, también se puede escribir en nuestro código de salida de forma presencial.

11.4.3 Método 3  usando anotaciones

Paso 1: escriba una clase mejorada para la implementación de anotaciones

/**
 * @Aspect 标注该类是一个切面
 */
@Aspect
public class AnnotationPointCut {
    @Before("execution(* com.gcx.Service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("-----方法执行前-------");
    }
    @After("execution(* com.gcx.Service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("-----方法执行后------");
    }


    /**
     *
     * @param jp 连接点
     */
    //    在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
    @Around("execution(* com.gcx.Service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("======环绕前=====");
//        执行方法,此句代码的执行就表示切入点方法的执行
        Object o = jp.proceed();
        System.out.println("=====环绕后======");
        System.out.println(o);
    }
}

Paso 2: en el archivo de configuración de Spring, registre el bean y agregue configuraciones que admitan anotaciones

    <bean id="annotationPointCut" class="com.gcx.log.AnnotationPointCut"/>
<!--    开启注解支持  -->
    <aop:aspectj-autoproxy/>
<!--    Spring代理模式有两种:  1. JDK(默认)  2.CGlib
                               当proxy-target-class为false使用默认JDK;
                               当proxy-target-class为true使用CGlib;
                               -->
<!--    <aop:aspectj-autoproxy proxy-target-class="false"/>-->

prueba

@Test
    public void LogTest(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserSerice userService = context.getBean("userService", UserSerice.class);
        userService.add();
    }

resultado de salida

======环绕前=====
-----方法执行前-------
增加了一个用户
=====环绕后======
null
-----方法执行后------

11.5 Resumen de AOP "Heart Bleeding"

Categoría de fórmula de declaración de corte de punto:
    1. El corte de punto es el método com.gcx.Service.UserServiceImpl().
        <aop:pointcut id="pointcut1" expression="execution(* com.gcx.Service.UserServiceImpl())"/>
    2. El pointcut son todos los métodos en la clase com.gcx.Service que no tienen valor de retorno y parámetros vacíos.
        <aop:pointcut id="pointcut2" expression= "execution(void com.gcx.Service.*())" / >
    3. El pointcut son todos los métodos en la clase com.gcx.Service que no tienen valor de retorno y no requieren parámetros.
        <aop:pointcut id="pointcut3" expression="execution(void com.gcx.Service.* (.. ))"/>
    4. Pointcut son todos los métodos en la clase com.gcx.Service que no tienen requisitos para el valor de retorno y el parámetro está vacío.
        <aop:pointcut id="pointcut4" expression="execution (* com.gcx.Service. *())"/>
    5. El pointcut es todos los métodos en la clase com.gcx.Service, y no hay ningún requisito para el valor devuelto y los parámetros.
        <aop:pointcut id="pointcut5" expresión="ejecución(* com.gcx.Service.*(..))"/>
    6. Pointcut son todos los métodos de todas las clases en el paquete com.gcx., y no hay ningún requisito para los valores y parámetros de retorno.
        <aop:pointcut id="pointcut6" expression="execution(* com.gcx. *.*(. .))"/>
    7. El pointcut es el método UserServiceImpl de todas las clases en el paquete com.gcx. No hay requisitos para el valor devuelto y los parámetros.
        <aop:pointcut id="pointcutbag6" expresión ="execution(* com.gcx .*.UserServiceImpl(..))"/>
    8. Para todos los métodos de todas las clases, no hay requisitos para los valores de retorno y los parámetros.        
        <aop:pointcut id="pointcutbag7" expresión="ejecución(* *(..))"/>

Estrategia de notificación y orden de ejecución:
    1. Pre-notificación (antes): Notificación ejecutada antes de la ejecución del método objetivo
    2. Post-notificación (después): Notificación ejecutada después de la ejecución del método objetivo.
    3. Lanzamiento posterior: la notificación que se ejecuta cuando el método de destino lanza una excepción.
    4. Después de la devolución: Notificación de que el método de destino se ejecutó con éxito.
    5. Notificación envolvente (alrededor): la notificación de que se puede ejecutar código adicional antes y después de la ejecución del método de destino
    <!--El orden de ejecución de la notificación está relacionado con el orden de configuración en el archivo xml -->
        / /El método para rodear la notificación debe seguir las siguientes reglas de definición de    
        //1: debe tener un parámetro de tipo ProceedingJoinPoint,     //2         :
        debe tener un valor de retorno de tipo Object    
        //3: ejecutar Object v = point.proceed( ); entre la lógica empresarial mejorada antes y después    
de /4: el método devuelve return v al final;
    Ejemplo: public Object method5(ProceedingJoinPoint point) throws Throwable {                System.out.println("~~~~~~~~~~ ~~~ notificación envolvente antes de ~~~~~~ ~~~~~");

    //point.proceed (args) indica el método de solicitud de ejecución, antes de este método, indica el punto de corte previo, y después de este método, indica el punto de corte posterior, la ejecución de esta sentencia significa la ejecución del punto método de corte.Object v = point.proceed
    ( );
    System.out.println("~~~~~~~~~~~~~ notificación envolvente después de~~~~~~~~~~~~~" );
    devuelve v;
    } 

 Resumen de reglas de notificación:
    Usando la configuración xml, el orden de ejecución de las notificaciones está relacionado con el orden de configuración.
    1. Usar notificación previa, notificación posterior, notificación final
        1.1 Sin notificación previa anormal > método de punto de entrada -> notificación posterior y notificación final (el orden de ejecución está determinado por el orden de configuración xml) 1.2
        Notificación previa > punto de entrada con método de excepción -> notificación posterior > notificación de excepción
    2. notificación envolvente, notificación de excepción
        2.1 sin excepción: notificación envolvente previa > método de punto de entrada > notificación envolvente posterior
        2.2 con excepción: notificación envolvente previa > método de punto de entrada > notificación de excepción
    3. Usar todas las notificaciones:
        3.1 Sin excepción: La secuencia de ejecución es la siguiente:
            3.1.1 Aviso previo y notificación previa al entorno (de acuerdo con el orden de configuración xml)
            3.1.2 Método de punto de entrada
            3.1.3 Notificación posterior, notificación final, posición posterior de notificación envolvente (Hay dos casos de ejecución según el orden de configuración xml. Uno es que existe frontal o envolvente, y el otro es que tanto frontal como envolvente existen sin otras configuraciones en el medio.) 3.2 Hay excepciones: la secuencia de ejecución es la siguiente: 3.2.1             Notificación previa             3.2.2 Método de punto de entrada
        Notificación             posterior, notificación de excepción (la secuencia de ejecución es la misma que la anterior)     Resumen: cuando no hay otros elementos de configuración entre el frente y surround, post,Exception, el orden de ejecución final es el mismo que el de la configuración



12. Transacciones declarativas 

1. ¡Las transacciones son muy importantes en el proceso de desarrollo del proyecto, involucrando problemas de "consistencia" de datos!
2. La gestión de transacciones es una tecnología esencial en el desarrollo de aplicaciones a nivel empresarial para garantizar la integridad y coherencia de los datos.
3. Una transacción consiste en tratar una serie de acciones como una unidad de trabajo independiente. Estas acciones se completan todas o no funcionan.

 12.1 Cuatro atributos de las transacciones

1. Atomicidad: una transacción es una operación atómica que consta de una serie de acciones. La atomicidad de una transacción garantiza que las acciones se completen o no se completen. 2. Coherencia: una vez que se completen todas las
acciones transaccionales, la transacción se confirmará. . Los datos y los recursos se encuentran en un estado consistente que satisface las reglas comerciales
3. Aislamiento: varias transacciones pueden procesar los mismos datos al mismo tiempo, por lo que cada transacción debe aislarse de otras transacciones para evitar la corrupción de datos
4. Persistencia: una vez que se completa la transacción , no importa qué error ocurra en el sistema, el resultado no se verá afectado. Por lo general, los resultados de las transacciones se escriben en un almacenamiento persistente

12.2 Gestión de transacciones en Spring 

Spring admite la gestión programática de transacciones y la gestión declarativa de transacciones.
1. Transacción declarativa AOP:
generalmente más fácil de usar que las transacciones programáticas.
Separe el código de gestión de transacciones de los métodos comerciales e implemente la gestión de transacciones de forma declarativa.
Tomar la gestión de transacciones como una preocupación transversal y modularizarla a través del método AOP. Spring admite la gestión de transacciones declarativas a través del marco Spring AOP.
2. Transacciones programáticas: necesidad de gestionar las transacciones en el código:
incrustar el código de gestión de transacciones en los métodos comerciales para controlar la confirmación y reversión de transacciones.
Desventajas: se debe incluir un código de gestión de transacciones adicional en la lógica empresarial de cada operación de transacción.

12.2.1 Administrador de transacciones 

Independientemente de la estrategia de gestión de transacciones (programática o declarativa) que utilice Spring, se requiere un administrador de transacciones.
Es la abstracción central de gestión de transacciones de Spring que encapsula un conjunto de métodos independientes de la tecnología.

12.3 Funciones de propagación de transacciones de Spring 

El comportamiento de propagación de transacciones es cómo las transacciones se propagan entre múltiples métodos de transacción cuando se llaman entre sí. Spring admite 7 tipos de comportamientos de propagación de transacciones:
1.propagation_requierd: si no hay una transacción actualmente, cree una nueva transacción, si ya hay una transacción, únase a esta transacción, esta es la opción más común.
2.propagation_supports: admite la transacción actual, si no hay una transacción actual, se ejecutará en un método no transaccional.
3.propagation_mandatory: use la transacción actual, si no hay una transacción actual, se lanzará una excepción.
4.propagation_required_new: crea una nueva transacción, si hay una transacción actual, suspende la transacción actual.
5.propagation_not_supported: Realiza operaciones de manera no transaccional. Si hay una transacción actual, suspende la transacción actual.
6.propagation_never: realice operaciones de forma no transaccional y genere una excepción si existe la transacción actual.
7.propagation_nested: si existe una transacción actualmente, ejecútela dentro de una transacción anidada. Si no hay una transacción actual, realice operaciones similares a propagation_required.El
comportamiento de propagación de transacciones predeterminado de Spring es PROPAGATION_REQUIRED, que es adecuado para la mayoría de las situaciones.

12.4 Importación restringida de archivos de encabezado 

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

12.5 Caso 

Clase de entidad (debido a que desea escribir una inyección de constructor, debe establecer parámetros vacíos y métodos de construcción parametrizados)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private int pwd;
}

Asignador de usuarios

public interface UserMapper {
//    查询全部用户信息
    List<User> selectUser();
//    添加一个用户
    int addUser(User user);
//    根据id删除一个用户
    int deleteUser(int id);
}

UserMapper.xml (escribir sentencia sql)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gcx.mapper.UserMapper">
    <select id="selectUser" resultType="user">
        select *from user;
    </select>
    <insert id="addUser" parameterType="user">
        insert into user (id,name,pwd) values(#{id},#{name},#{pwd})
    </insert>
    <delete id="deleteUser" parameterType="int">
        delete from user where id = #{id}
    </delete>

</mapper>

mybatis-config.xml (archivo de configuración del mapeador)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--核心配置文件-->
<configuration>
<!--别名管理-->
    <typeAliases>
        <package name="com.gcx.pojo"/>
    </typeAliases>
//使用Spring绑定配置文件,省略配置mapper命名空间
</configuration>

primavera-dao.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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--DataSource:使用Spring的数据源替换Mybatis的配置  c3p0 dbcp druid
这里使用Spring提供的jdbc:org.springframework.jdbc.datasource-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>


    <!--    配置sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="datasource"/>
<!--    绑定Mybatis配置文件-->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    <property name="mapperLocations" value="classpath:com/gcx/mapper/*.xml"/>
</bean>
<!--   SqlSessionTemplate:就是我们使用的SqlSession -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--    只能使用构造器注入SqlSessionFactory,因为没有set方法-->
    <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
    <!--    配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="datasource"/>
    </bean>
    <!--    结合AOP,实现事务的置入-->
    <!--    配置事务通知:-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--        给那些方法配置事务:-->
        <tx:attributes>
            <!--            配置事务的传播特性:propagation 默认为 REQUIRED-->
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <!--            read-only:只读-->
            <tx:method name="query" read-only="true"/>
            <!--            配置所有方法-->
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--    配置事务切入-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.gcx.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

  applicationContext.xml (archivo de configuración de Spring)

<?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">
    <import resource="spring-dao.xml"/>
    <bean id="userMapper" class="com.gcx.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>
</beans>

UserMapperImpl (clase de implementación)

/**
 * 另一种写法,直接继承SqlSessionDaoSupport;
 * public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{}
 * 该方法内部已经写好了构造SqlSessionTemplate类型的变量sqlSession,并创建了SqlSessionFactory工厂
 */
public class UserMapperImpl implements UserMapper{
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }
    public List<User> selectUser() {
        User user = new User(7, "小孟", 123134);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.addUser(user);
        mapper.deleteUser(6);
        return mapper.selectUser();
    }


    public int addUser(User user) {
        return sqlSession.getMapper(UserMapper.class).addUser(user);
    }

    public int deleteUser(int id) {
        return sqlSession.getMapper(UserMapper.class).deleteUser(id);
    }
}

prueba prueba

public class Mytest {
    @Test
    public void test(){
        ApplicationContext Context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = Context.getBean("userMapper", UserMapper.class);
        List<User> users = userMapper.selectUser();

        for (User user : users) {
            System.out.println(user);

        }
    }
}

 resultado de salida

User(id=1, name=小顾, pwd=123456)
User(id=2, name=小董, pwd=123666)
User(id=3, name=小杨, pwd=1234567)
User(id=4, name=小孟, pwd=1234567)
User(id=5, name=小鑫, pwd=122223)
User(id=7, name=小孟, pwd=123134)

13. Auto-resumen periódico

Después de casi dos semanas de autoaprendizaje, entiendo qué es Spring. Los dos puntos principales de la entrevista, "inversión de control IOC" y "programación de aspecto AOP", son más difíciles de aprender; comprenda el archivo de configuración de Spring. Cómo escribir, qué se incluye en él, para qué se usa, N múltiples formas de inyección de beans, cómo usar Spring para conectarse automáticamente a la base de datos, no necesita ser tan engorroso como JDBC, dos modos de proxy diferentes, varios métodos AOP para implementar mejoras de código , varias notificaciones y transacciones declarativas.

Lo más afortunado es que en el proceso de escribir estos códigos, encontré muchos problemas y reporté muchos errores, pero no me di por vencido. Varios Baidu y csdn buscaron soluciones a los problemas, así que continúen trabajando duro y perseverando, y habrá progreso!

Supongo que te gusta

Origin blog.csdn.net/m0_74135466/article/details/128227021
Recomendado
Clasificación