Resumen y revisión de las notas de estudio de Spring (Crazy God said java)

Notas de estudio de primavera

1 primavera

1.1 Introducción

<!-- 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 Composición

inserte la descripción de la imagen aquí

1.3 Ventajas

● Diseño no intrusivo

Spring es un marco no invasivo que minimiza la dependencia del código de la aplicación en el marco.
● Desacoplamiento conveniente y desarrollo simplificado

Spring es una gran fábrica, que puede entregar la creación de todos los objetos y el mantenimiento de las dependencias a la gestión de contenedores de Spring, lo que reduce en gran medida el acoplamiento entre los componentes.
● Apoyar AOP

Spring brinda soporte para AOP, lo que permite el procesamiento centralizado de algunas tareas comunes, como seguridad, transacciones, registros, etc., mejorando así la reutilización de los programas.
● Admite el procesamiento de transacciones declarativas

La gestión de transacciones se puede completar solo a través de la configuración, sin programación manual.
● Prueba de programa conveniente

Spring brinda soporte para Junit4, que puede probar fácilmente los programas de Spring a través de anotaciones.
● Reducir la dificultad de usar la API de Java EE.

Spring proporciona paquetes para algunas API que son muy difíciles de usar en el desarrollo de Java EE (como: JDBC, JavaMail, etc.), lo que reduce en gran medida la dificultad de aplicar estas API.

Dos características principales de Spirng

  • Inversión de Control (IOC), Programación Orientada a Aspectos (AOP)

2.COI

1. Interfaz UserDao

public interface UserDao {
    
    
    void getUser();
}

2. Clase de implementación UserDaoImpl

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

3. Interfaz empresarial de UserService

public interface UserService {
    
    
    void getUser();
}

4. Clase de implementación empresarial UserServiceImpl

public class UserServiceImpl implements UserService {
    
    

    private UserDao userDao = new UserDaoImpl();

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

5. prueba

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

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

inserte la descripción de la imagen aquí
Aquí, la inyección de conjuntos se usa para cambiar la iniciativa del programa original del programador al usuario. Los usuarios pueden llamar al método que deseen, lo que reduce en gran medida la presión sobre los programadores para modificar el código.

    private UserDao userDao;

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

esencia del COI

La inversión de control (IOC) es una idea de diseño, y la inyección de dependencia DI es un método para realizar IOC. Sin IOC, usamos programación orientada a objetos. La creación de objetos está controlada por el programa, es decir, nuestros programadores. Después de usar IOC, la iniciativa de creación de objetos se invierte.
A través de xml o anotaciones, para obtener la forma de generar un objeto específico, se utiliza el contenedor IOC para implementar la inversión de control en Spring, y el método de implementación es DI.

3.Hola mundo

Solo construye un proyecto maven

clase de entidad

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>

última prueba

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());
    }
}
  • En este momento, el contenedor Spring crea el objeto y Spring también establece sus propiedades.
    ¡Este proceso es Inversión de Control!

4. COI crea objetos

En el momento en que se cargan el xml u otros archivos de configuración, el objeto ya se ha inicializado.
De forma predeterminada, Spring crea objetos utilizando la construcción sin argumentos. Por supuesto, también podemos utilizar la construcción de parámetros para crear objetos.
1. Asignación de subíndices

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

2. Tipo (no recomendado)

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

3. Nombre del parámetro

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

5. Configuración de resorte

5.1 Alias

Si se agrega un alias, también podemos usar el alias para obtener este objeto.

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

Para hacer el código más conciso o reducir la cantidad de código.

5.2 Configuración de frijoles

  • id: el identificador único del bean, que es equivalente a nuestro nombre de objeto

  • clase: el nombre completo correspondiente al objeto bean: nombre del paquete + nombre de la clase

  • nombre: también es un alias, y el nombre puede tomar varios alias al mismo tiempo

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

5.3 importar archivos combinados

Generalmente se usa para el desarrollo de equipos, puede importar y fusionar múltiples archivos de configuración en uno.
Zhang San desarrolla un xml, Li Si desarrolla un xml, Wang Wu desarrolla un xml y finalmente crea un application.xml y usa import para importar y fusionar en un xml.
No escribiré código aquí, solo entiéndelo.

6. Inyección de dependencia

6.1 Inyección de constructor

No se repetirá aquí la construcción de parámetros (por defecto de resorte) y la construcción de parámetros, como se mencionó anteriormente.

6.2 Inyección del método Set ···Puntos clave···

  • Inyección de dependencia: Inyección de conjunto
  • ¡Todos los valores de atributo del objeto son inyectados por el contenedor de resorte!
    【Construcción del entorno】
    1. Tipo complejo
public class Address {
    
    
    private String address;

    public String getAddress() {
    
    
        return address;
    }

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

2. Objeto de prueba

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, 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"
       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. 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.getName());
    }
}

5. Finalmente completa la información

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

Los espacios de nombres p y c también se pueden inyectar,
lo que requiere restricciones de importación

       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 Alcance de los frijoles

  • modo singleton (predeterminado)
<bean id="user2" class="com.kuang.pojo.User" c:name="狂神" c:age="22" scope="singleton"/>
  • Modo prototipo: ¡Cada vez que salgas del contenedor, se generará un nuevo objeto!
<bean id="user2" class="com.kuang.pojo.User" c:name="狂神" c:age="22" scope="prototype"/>

7. Método de ensamblaje automático (frijol)

  • ¡Spring lo buscará automáticamente en el contexto y ensamblará automáticamente las propiedades para el bean!
    1. Configuración explícita en xml
    2. Configuración explícita en java
    3. Bean ensamblador automático implícito **

7.1 Pruebas

¡Crea nuevos módulos, una persona y dos mascotas!

    <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 Apodos

  • byName: ¡Buscará automáticamente en el contexto del contenedor y la identificación del bean correspondiente al valor detrás del método set de su propio objeto!
        <bean id="people" class="com.kuang.pojo.People" autowire="byName">
            <property name="name" value="小白莲"/>
        </bean>

7.3 Por tipo

  • byType: ¡Encontrará automáticamente beans del mismo tipo que sus propias propiedades de objeto en el contexto del contenedor!
        <bean id="people" class="com.kuang.pojo.People" autowire="byType">
            <property name="name" value="小白莲"/>
        </bean>

Aviso:

  • Cuando ByName, debe asegurarse de que la identificación de todos los beans sea única, y este bean debe ser coherente con el valor del método set de la propiedad inyectada automáticamente.

  • Cuando ByType, es necesario asegurarse de que la clase de todos los beans sea única, ¡y este bean debe ser coherente con el tipo de la propiedad inyectada automáticamente!

7.4 Implementación mediante anotaciones

¡Spring2.5 y superior admiten anotaciones, y jdk1.5 y superior admiten anotaciones!
1. Restricciones de importación
2. Soporte para anotaciones de configuración

<?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
se puede usar directamente en la propiedad! ¡También se puede usar en métodos establecidos!

prueba

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

Cuando no se puede completar el ensamblaje automático, use @Qualifier(value = "xxx") para configurar el uso de @Autowired y especifique un objeto bean único para inyectar.

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

@Recurso

public class People {
    
    

    @Resource
    private Cat cat;

    @Resource
    private Dog dog;
}

La diferencia entre @Resource y @Autowired:

  • Ambos se utilizan para el ensamblaje automático y se pueden colocar en el campo de atributo

  • @Autowired está implementado por byType, ¡y se debe requerir que este objeto exista! [comúnmente utilizado]

  • @Resource lo realiza byName de forma predeterminada, si no se puede encontrar el nombre, ¡lo realiza byType! Si ninguno de ellos se puede encontrar, informe de un error. [comúnmente utilizado]

  • El orden de ejecución es diferente: @Autowired es implementado por byType.

8. Desarrollo de anotaciones

Después de Spring4, básicamente se utiliza el desarrollo de anotaciones.
¡El uso de anotaciones requiere la importación de restricciones y el soporte de anotaciones de configuración!

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

Cómo se inyectan las propiedades del frijol

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

@Component
public class User {
    
    

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

anotación derivada

  • @Componente
  • dao 【@Repositorio】
  • servicio 【@Servicio】
  • controlador [@Controller]
    tiene la misma función, registra una clase en Spring y ensambla beans para el
    ensamblaje automático
  • @Autowired: Autowire por tipo, nombre. Si Autowired no puede ensamblar automáticamente el atributo de forma única, debe configurarse a través de @Qualifier(value = "xxx").
  • El campo @Nullable marca esta anotación, lo que indica que este campo puede ser nulo;
  • @Resource: Autocableado por nombre, tipo.
    La diferencia entre xml y anotaciones
    xml se usa para administrar beans;
    las anotaciones solo se encargan de completar la inyección de atributos; ¡
    xml es más versátil y adecuado para cualquier ocasión! Mantenimiento simple y conveniente
    Si las anotaciones surten efecto, ¡debe habilitar el soporte de anotaciones!
    <!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.kuang"/>
    <!--开启注解的支持    -->
    <context:annotation-config/>

9. Manera Java de configurar Spring

De ahora en adelante, no use la configuración xml de Spring, ¡y déjelo en Java!

clase de entidad

//这里这个注解的意思,就是说明这个类被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 + '\'' +
                '}';
    }
}

archivo de configuración

// 这个也会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的对象!
    }
}

prueba

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

¡Este método se usa a menudo en springboot!

10. Modo proxy

El modo proxy es el principio subyacente de aop!
inserte la descripción de la imagen aquí

10.1 Proxy estático

  • Rol abstracto: Generalmente, se utilizan interfaces o clases abstractas para resolver
  • Rol real: Rol delegado
  • Rol de actuación: actuando como un personaje real, después de actuar como un personaje real, generalmente hacemos algunas operaciones auxiliares
  • cliente: ¡la persona que accede al objeto proxy!
    papel abstracto
//租房
public interface Rent {
    
    
    public void rent();
}

personaje real

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

rol de agente

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("中介收取费用!");
    }
}

Rol de agente de acceso de cliente

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

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

        //不用面对房东,直接找中介租房即可!
        proxy.rent();
    }
}
  • ¡Puede hacer que la operación de personajes reales sea más pura! No hay necesidad de prestar atención a algunos asuntos públicos

  • ¡El rol público se entrega al rol de proxy! ¡La división del trabajo se ha realizado!

  • ¡Cuando el negocio público se expande, es conveniente para la gestión centralizada!
    Sin embargo, la cantidad de código se duplicará y la eficiencia de desarrollo será menor.

10.2 Profundizar la comprensión

papel abstracto

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

personaje real

//真实角色
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("查询了一个用户!");
    }
}

rol de agente

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+"方法");
    }
}

Rol de agente de acceso de cliente

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 dinámico

  • Su clase proxy se genera dinámicamente
  • Se puede dividir en dos categorías:
    1. Basado en la interfaz: proxy dinámico JDK
    2. Basado en la clase: cglib
    3. Implementación del código de bytes de Java: javassist
    aquí para obtener información sobre la clase de proxy (Proxy) por adelantado;
    resumen del controlador de llamadas (invocationHandler) role
public interface Rent {
    
    
    public void rent();
}

**Personaje real

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

Clase ProxyInvocationHandler

//我们会用这个类,自动生成代理类!
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("中介收取费用!");
    }
}

prueba

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();

    }
}

Presentar ProxyInvocationHandler como una clase de herramienta

//用这个类自动生成代理类!
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+"方法");
    }
}

Beneficios de los proxies dinámicos:

  • ¡Puede hacer que la operación de personajes reales sea más pura! No hay necesidad de prestar atención a algunos asuntos públicos
  • ¡El rol público se entrega al rol de proxy! ¡La división del trabajo se ha realizado!
  • ¡Cuando el negocio público se expande, es conveniente para la gestión centralizada!
  • Una clase de proxy dinámico representa una interfaz, que generalmente corresponde a un tipo de negocio
  • Una clase de proxy dinámico puede representar múltiples clases, ¡siempre que se implemente la misma interfaz!

11, AOP

11.1 Introducción a POA

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.
inserte la descripción de la imagen aquí

11.2 El papel de AOP en Spring

Proporciona transacciones declarativas; permite aspectos definidos por el usuario

  • Preocupaciones transversales: métodos o funciones que abarcan varios módulos de una aplicación. Es decir, la parte que no tiene nada que ver con nuestra lógica de negocio, pero a la que debemos prestar atención, es la transversalidad. Tales como registro, seguridad, almacenamiento en caché, transacciones, etc.
  • ASPECTO: Un objeto especial donde se modularizan preocupaciones transversales. Es decir, es una clase.
  • Consejo: El trabajo que el aspecto debe completar. Es decir, es un método en la clase.
  • Target: El objeto a ser notificado.
  • Proxy: un objeto creado después de que se aplica una notificación a un objeto de destino.
  • PointCut: Definición del "lugar" donde se ejecutan los consejos de aspecto.
  • Punto de conexión (JointPoint): El punto de ejecución que coincide con el punto de corte.
    inserte la descripción de la imagen aquí
    Spring admite 5 tipos de consejos:
    inserte la descripción de la imagen aquí
    aop es agregar nuevas funciones sin cambiar el código original.

11.3 Implementando AOP con Spring

¡Para usar el tejido AOP, debe importar un paquete de dependencia!

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

1. Use la interfaz API de Spring [principalmente la implementación de la interfaz API de Spring]
en el paquete de servicios, defina la interfaz comercial UserService y la clase de implementación 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("查询了一个用户!");
    }
}

En el paquete de registro, defina nuestra clase de mejora, una mejora previa de registro y una clase de mejora posterior a 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);
    }
}

Finalmente, regístrese en el archivo de primavera e implemente la implementación de corte de aop, preste atención a las restricciones de importación y configure el archivo 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>

prueba

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. Personalice la clase para implementar AOP [principalmente definición de aspecto]
defina su propia clase de corte DiyPointCut en el paquete diy

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

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

archivo de configuración

    <!--方式二:自定义类-->
    <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>

En tercer lugar, ¡use anotaciones para lograrlo!
Clase mejorada AnnotationPointCut definida en el paquete diy para la implementación de anotaciones

//声明式事务!
@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);
    }

}

En el archivo de configuración de Spring, registre el bean y agregue configuraciones que admitan anotaciones.

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

12. Transacciones declarativas

12.1 Revisión de transacciones

  • Trate a un grupo de negocios como un solo negocio; ¡o todos tienen éxito o todos fracasan!

  • Las transacciones son muy importantes en el desarrollo de proyectos. Cuando se trata de la consistencia de los datos, ¡no se puede ser descuidado!

  • Garantizar la integridad y la coherencia.
    Transacción Principios ACID:

  • Atomicidad

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

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

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

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

prueba:

Copie el código anterior a un nuevo proyecto
En el caso anterior, agregamos dos métodos a la interfaz de userMapper, eliminar y agregar usuarios;
copiar el código anterior a un nuevo proyecto
En el caso anterior, le dimos a userMapper Agregamos dos métodos a la interfaz, eliminar y agregar usuarios;

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

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

En el archivo UserMapper, deliberadamente escribimos mal las eliminaciones, ¡prueba!

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

Escriba la clase de implementación UserMapperImpl de la interfaz.En la clase de implementación, operaremos una onda

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);
    }
}

prueba

    @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);
        }
    }

Error: excepción de sql, la eliminación está mal escrita

Resultado: ¡El resultado de la base de datos muestra que la inserción fue exitosa!

No hay gestión de transacciones, queremos que todos tengan éxito para tener éxito, y si uno falla, todos fallan. ¡Deberíamos necesitar transacciones!

En el pasado, todos necesitábamos administrar manualmente los asuntos por nosotros mismos, ¡lo cual era muy problemático!

Pero Spring nos proporciona la gestión de transacciones, solo necesitamos configurar;

12.2 Gestión de transacciones en Spring

gestión programática de transacciones

  • Incruste el código de gestión de transacciones en los métodos comerciales para controlar el compromiso y la reversión de transacciones
  • Desventaja: Se debe incluir un código de gestión de transacciones adicional en cada operación de transacción Lógica empresarial
    Gestión de transacciones declarativa
  • 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.
    Use Spring para administrar transacciones, preste atención a la importación de restricciones del archivo de encabezado: tx
xmlns:tx="http://www.springframework.org/schema/tx"

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

transacción JDBC

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

Después de configurar el administrador de transacciones, debemos configurar las notificaciones de transacciones.

    <!--结合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>

Funciones de propagación de transacciones de Spring:
el comportamiento de propagación de transacciones es cómo las transacciones se propagan entre estos métodos cuando varios métodos de transacción se llaman entre sí. Spring admite 7 comportamientos de propagación de transacciones:

  • propagación_requierd: si no hay ninguna 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.
  • propagation_supports: admite la transacción actual, si no hay una transacción actual, se ejecutará en un método no transaccional.
  • propagation_mandatory: usa la transacción actual y lanza una excepción si no hay una transacción actual.
  • propagation_required_new: crea una nueva transacción, si hay una transacción actual, suspende la transacción actual.
  • propagación_not_supported: realizar operaciones de forma no transaccional. Si hay una transacción actual, suspender la transacción actual.
  • propagation_never: realiza la operación de forma no transaccional, lanzando una excepción si existe la transacción actual.
  • propagation_nested: Ejecutar dentro de una transacción anidada si hay una transacción actual. Si no hay ninguna transacción actualmente, realice una operación similar 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.
    Configure AOP, importe el archivo de encabezado de aop
    <!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

¡Elimine los datos que acaba de insertar y vuelva a probar!

    @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);
        }
    }

¿Por qué necesita transacciones?

  • Si no configura transacciones, puede haber inconsistencias en el envío de datos;

  • Si no configuramos transacciones declarativas en Spring, ¡necesitamos configurar manualmente las transacciones en el código!

  • Las transacciones son muy importantes en el desarrollo del proyecto, lo que involucra problemas de integridad y consistencia de datos, ¡y no deben ser descuidados!
    Los videos del maestro Kuangshen son realmente muy adecuados para que el público los aprenda, y he ganado mucho en el proceso de verlos y aprender. ¡Sigamos el video del Sr. Kuangshen y animemos juntos! ¡Programador!

Supongo que te gusta

Origin blog.csdn.net/lj20020302/article/details/129300548
Recomendado
Clasificación