Explicar los principios y métodos de la programación orientada a aspectos de Spring AOP.

1. ¿Qué es AOP?

AOP (Programación Orientada a Aspectos) significa: Programación Orientada a Aspectos, mediante precompilación e implementación de agentes dinámicos en tiempo de ejecución, sin modificar el código fuente, una tecnología para agregar dinámicamente funciones al programa, puede entenderse como un agente dinámico. Es una parte importante del marco de Spring. El uso de AOP puede aislar cada parte de la lógica empresarial, reducir el acoplamiento entre las diversas partes de la lógica empresarial, mejorar la reutilización del programa y mejorar la eficiencia del desarrollo al mismo tiempo.

2. Primavera AOP

①. El rol de AOP en Spring
Proporciona transacciones declarativas; permite a los usuarios personalizar aspectos

②. El concepto básico de AOP Se
refiere a temas transversales: métodos o funciones que abarcan varios módulos de una aplicación. Es decir, no tiene nada que ver con nuestra lógica empresarial, pero la parte que necesita nuestra atención es el enfoque transversal. Como registro, seguridad, caché, transacciones, etc.

  • Aspecto: Objetos especiales cuyas preocupaciones transversales están modularizadas. Por lo general, una clase, que puede definir puntos de entrada y notificaciones.
  • Tejido: conecte aspectos con otros tipos de aplicaciones u objetos y cree un objeto recomendado. Estos se pueden hacer en tiempo de compilación, tiempo de carga de clase y tiempo de ejecución. Spring, al igual que otros marcos de Java AOP puros, completa el tejido en tiempo de ejecución
  • Aviso (notificación): El procesamiento mejorado realizado por AOP en un punto de corte específico es el trabajo que debe realizar el aspecto, y también es un método en la clase.
  • Target (target): el objeto notificado
  • AOP (Proxy): el objeto creado por el marco AOP y el proxy es la mejora del objeto de destino. * El proxy AOP en Spring puede ser un proxy dinámico JDK o un proxy CGLIB, el primero se basa en interfaces y el segundo en subclases.
  • JointPoint (punto de conexión): un punto claro durante la ejecución del programa, generalmente una llamada a un método
  • Pointcut (pointcut): es el punto de conexión con notificación, el punto de ejecución que coincide con el pointcut
    ③. Use Spring para lograr los
    requisitos previos de Aop
    Use AOP weaving, necesita importar un paquete de dependencia
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.5</version>
</dependency>

Tres formas de lograr Aop

Método 1: Implementación a través de Spring API [principalmente implementación de la interfaz Spring API]

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

public interface UserService {
  public void add();
  public void delete();
  public void update();
  public void search();
}
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("查询了一个用户");
  }
}

Luego, escriba clases mejoradas, aquí hay dos: Registro premejorado y AfterLog posmejorado

import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
  //method: 要执行的目标对象的方法
  //args: 参数
  //target: 目标对象
  public void before(Method method, Object[] args, Object target) throws Throwable {
    System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
  }
}
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
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 Spring (applicationContext.xml) e implemente el corte AOP, preste atención a las restricciones de importació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: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.lf.service.UserServiceImpl"/>
  <bean id="log" class="com.lf.log.Log"/>
  <bean id="afterLog" class="com.lf.log.AfterLog"/>
  
  <!--方式一:使用原生Spring API接口 -->
  <!--配置aop:需要导入aop的约束-->
  <aop:config>
  <!--切入点:expression:表达式,execution(要执行的位置! * * * * *) -->
  <aop:pointcut id="pointcut" expression="execution(* com.lf.service.UserServiceImpl.*(..))"/>
  <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
  <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
  <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
  </aop:config>

</beans>

realizar pruebas:

import com.lf.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
  @Test
  public void test(){
  ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  UserService userService1 = (UserService) context.getBean("userService");
  UserService userService = (UserService) context.getBean("userService");
  userService.add();
  }
}

resultado de la operación:

com.lf.service.UserServiceImpl的add被执行了
增加了一个用户
执行了add方法,返回结果为:null

Método 2: la clase personalizada implementa AOP [principalmente la definición de aspecto] La
clase de negocio de destino permanece sin cambios, o UserServiceImpl en el primer método

Escribe una clase corta

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

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

Configurar en Spring (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.lf.service.UserServiceImpl"/>
  <bean id="log" class="com.lf.log.Log"/>
  <bean id="afterLog" class="com.lf.log.AfterLog"/>
  
  <!--方式二:自定义类-->
  <bean id="diy" class="com.lf.diy.DiyPointCut"/>

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

Pruebe en MyTest.java arriba y obtenga el resultado:

Antes de que se ejecute el método=
Añadido un usuario
Después de que se ejecuta el método=

Método 3: use anotaciones para lograr [multipropósito]
escribir una clase mejorada para anotaciones

package com.lf.diy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect //标注这个类是一个切面
public class AnnotationPointCut {

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

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

  //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点;
  @Around("execution(* com.lf.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 la configuración que admita anotaciones

<?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.lf.service.UserServiceImpl"/>
  <bean id="log" class="com.lf.log.Log"/>
  <bean id="afterLog" class="com.lf.log.AfterLog"/>

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

Prueba en MyTest.java

import com.lf.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
  @Test
  public void test(){
  ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  UserService userService = (UserService) context.getBean("userService");
  userService.add();
  }
}

tengo la respuesta:

环绕前
signature:void com.lf.service.UserService.add()
=====方法执行前======
增加了一个用户
=====方法执行后======
环绕后
null

Algunas preguntas de entrevistas de alta frecuencia recopiladas en el último 2020 (todas organizadas en documentos), hay muchos productos secos, incluidos mysql, netty, spring, thread, spring cloud, jvm, código fuente, algoritmo y otras explicaciones detalladas, así como planes de aprendizaje detallados, entrevistas Clasificación de preguntas, etc. Para aquellos que necesitan obtener estos contenidos, agregue Q como: 11604713672

Supongo que te gusta

Origin blog.csdn.net/weixin_51495453/article/details/113645365
Recomendado
Clasificación