Comprensión de IOC y AOP

Preguntas de la entrevista: 1. Hable sobre su comprensión de IOC y AOP

Referencias:
Trate de explicar los conceptos básicos de
Spring IOC y AOP. Spring JdbcTemplate Explica
JDBC en Java en detalle
[Spring Basics] AOP usando anotaciones en la práctica

Respuesta: IOC es un contenedor de resorte, que puede ayudarnos a crear objetos sin necesidad de que los creemos manualmente. IOC tiene una potente inyección de dependencia funcional (DI), que puede gestionar mejor los Beans a través de la inyección de dependencia para lograr el propósito de desacoplamiento. Por ejemplo: la JDBCTemplate que usamos puede configurarse en xml, y luego inyectarse y usarse, pero necesitamos una fuente de datos, podemos cambiar la fuente de datos a voluntad, para que JDBCTemplate no fuerce la dependencia de una determinada fuente de datos para lograr el desacoplamiento .

Respuesta: AOP se usa a menudo en transacciones y registros, porque se puede ejecutar sin estar incrustado en el código.

2. Hablaré sobre el proceso de IOC, también existe el puntero de B + Tree que es propicio para la búsqueda de rango, la diferencia entre zookeeper y eureka, uno es http y el otro es RPC.

3. ¿Se pueden cambiar los parámetros del método objetivo en Aop?

1. IOC (modo de diseño: modo de fábrica)

1.1. Concepto: Es un contenedor de muelles que nos ayuda a crear objetos.

Dos, concepto Aop

Aop es un concepto, springAop y aspectJ son la realización de Aop. Si el front-end envía la solicitud al controlador al servicio y luego al dao de arriba a abajo, entonces springAop interviene desde el nivel, pero está completamente desacoplado para realizar algunas funciones, como el registro , transacción, excepción y permiso Espere. Realice algunas funciones del aspecto. Como registros, transacciones, permisos, excepciones, etc.

3. La conexión entre Aop y aspectJ

La gramática de Aop es más complicada, por lo que utiliza el estilo gramatical de aspectJ, pero la capa inferior todavía se implementa por sí misma.

Cuarto, el uso de Aop

4.1, abrir Aop

Habilite la compatibilidad con AspectJ a través de la anotación @Configuration y anote @EnableAspectJAutoProxy.
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
    
    


}

4.2, declarar una clase de aspecto (aspecto)

Declare una clase de anotación de Aspect y defina la clase como un Bean para la gestión de primavera.

4.2.1. Los aspectos incluyen notificaciones y puntos de entrada

@Component
@Aspect
public class AspectTest {
    
    

}

4.3. Escribir puntos de entrada y notificaciones en la categoría de aspecto

4.3.1. El punto de entrada es qué método de destino será notificado de la ejecución

4.3.2. La notificación es un método de ejecución en torno al método de destino

4.3.4. El código es el siguiente: (Se puede encontrar que las expresiones del punto de entrada son todas iguales, ¿cómo puedo eliminarlo?)

@Component
@Aspect
public class AspectTest {
    
    


    @Before("execution(* com.xuecheng.aop.service..*.*(..))")
    public void before() {
    
    
        System.out.println("before执行。。。。");
    }

    @After("execution(* com.xuecheng.aop.service..*.*(..))")
    public void after() {
    
    
        System.out.println("after执行。。。。");
    }

}

4.3.5. El código optimizado es el siguiente:


@Component
@Aspect
public class AspectTest {
    
    
    
    @Pointcut("execution(* com.xuecheng.aop.service..*.*(..))")
    public void pointCut() {
    
    

    }


    @Before("pointCut()")
    public void before(){
    
    
        System.out.println("before执行。。。。");
    }

    @After("pointCut()")
    public void after(){
    
    
        System.out.println("after执行。。。。");
    }



}

4.4, escribe el método de destino

4.4.1, código de interfaz

public interface FatherServ {
    
    

    public void ss();
}

4.4.2. Código de clase de implementación (clase de destino)

@Component("s")
public class TestService implements FatherServ {
    
    
    public void ss(){
    
    
        System.out.println("目标方法执行...");
    }
}

4.5. Los resultados de la prueba son los siguientes:

before执行。。。。
目标方法执行...
after执行。。。。

Cinco, el análisis de expresión de punto de entrada en Aop

Referencia: explicación detallada de la expresión de corte de puntos de Spring AOP

Inserte la descripción de la imagen aquí

Al ejecutar una expresión, podemos hacer coincidir la expresión con los operadores lógicos && (y), || (o),! (No). como:

execution(* com.jpeony.spring.ConferenceServiceImpl.conference(..)
       && within(com.jpeony.spring.*))

Una restricción adicional es que solo nos ocupamos de los paquetes en com.jpeony.spring. El && aquí se puede reemplazar por y, de
manera similar ||,! Son del mismo uso, flexibles y modificables, y solo se pueden manejar de acuerdo con el situación actual.

5.1, ejecución (la granularidad puede ser precisa para un método específico)

5.2, dentro (la granularidad solo puede ser precisa para la clase)

5.2.1 Exacto para la clase BusinessObject y mejore todos los métodos de esta clase.

within(com.spring.service.BusinessObject)

5.2.2, exacto para todas las clases del paquete de servicios, pero sin incluir las clases del subpaquete

within(com.spring.service.*)

5.2.3, exacto para las clases del paquete de servicios y todas las clases de subpaquetes del paquete

within(com.spring.service..*)

5.3, args (la granularidad es el método para hacer coincidir el número de parámetros y el tipo de parámetros)

5.3.1, el método de coincidir exactamente con un solo parámetro de tipo de cadena

args(java.lang.String)

5.3.2 Coincidir exactamente hasta que el parámetro sea de tipo String al principio y tipo Integer al final, y cualquier número y tipo de parámetros puede estar en el medio. Aquí los comodines usan "...", no "*"

args(java.lang.String,..,java.lang.Integer)

5.4, ​​la diferencia entre esto y el objetivo

5.4.1. Cuando se utiliza para la notificación envolvente, cuando el objeto de destino se especifica en this y target, si el objeto de destino no implementa una interfaz, el resultado de la ejecución es el mismo; si el objeto de destino implementa una interfaz, este no puede realizar la envolvente de notificación, pero el objetivo puede.

5.5 、 @ dentro

5.5.1 Cuando la granularidad coincide con las clases en las que se coloca la anotación especificada, las clases se mejoran.

5.6 、 @ anotación

5.6.1. Similar a @within, @annotation actúa sobre los métodos.

5.7 、 @ argumentos

5.7.1, indica que cuando la clase marcada con anotaciones se usa como parámetro, se mejora el método de ejecución

5.8 、 @ DeclareParents

5.8.1 Representa la introducción de nuevos atributos y métodos para la clase de destino especificada.

5.9 、 perthis 和 objetivo

5.9.1. En el caso de varios hilos, cree varias instancias de la clase Aspect

Seis, notificación envolvente

6.1. Las rodajas son las siguientes:

Paso 1: agregue una anotación @Around

Paso 2: Pase el parámetro ProceedingJoinPoint en el método de notificación y luego llame a su método continue ();


@Component
@Aspect
public class AspectTest {
    
    

    @Around("pointCut()")
    public void aroundTest(ProceedingJoinPoint proceedingJoinPoint) {
    
    
        try {
    
    
            System.out.println("环绕通知之前执行");
            proceedingJoinPoint.proceed();
            System.out.println("环绕通知之后执行");
        } catch (Throwable throwable) {
    
    
            System.out.println("异常通知执行。。");
        }
    }

    @Pointcut("execution(* com.xuecheng.aop.service..*.*(..))")
    public void pointCut() {
    
    

    }
}

Siete, los parámetros del método objetivo se pueden obtener y modificar

7.1 Pasar el parámetro JoinPoint en el método de notificación y llamar al método getArgs () para obtener los parámetros del método objetivo y modificarlo.

    @Around("execution(* com.xuecheng.aop.service..*.*(..))")
    public void aroundTest(JoinPoint JoinPoint) {
    
    
        //获取目标方法的参数,并可以对其进行修改
		// Object[] args = joinPoint.getArgs();
    }

8. Clasificación de los consejos

8.1. El aspecto Spring define 5 tipos de notificaciones:

1) Antes de la notificación (Antes): Se llama a la función de notificación antes de llamar al método de destino.

2) Después de la notificación (Después): llame a la notificación después de que se complete el método de destino y no le importe cuál sea el resultado del método. (Independientemente de si el método de destino se ejecuta con éxito o no, la notificación posterior debe ejecutarse).

3) Después de la devolución: la notificación se llama después de que el método de destino se ejecuta correctamente. (¡Ejecutado antes de la notificación posterior, el método debe ejecutarse correctamente antes de que pueda ejecutarse!)

4) Notificación de excepción (después del lanzamiento): notificación de llamada después de que el método de destino arroja una excepción.

5) Alrededor de la notificación (Alrededor): la notificación envuelve el método notificado y ejecuta un comportamiento personalizado antes y después de que se llame al método notificado. (El parámetro ProceedingJoinPoint puede tener, pero JoinPoint no puede existir).

ProceedingJoinPoint hereda de JoinPoint; hay dos métodos en ProceedingJoinPoint: proceda () y proceda (objeto objeto);

Nueve, terminología AOP

Punto de contacto, punto de conexión, aspecto, notificación

El punto de conexión es una colección de puntos tangentes y el punto de conexión es un concepto etéreo y de gran escala. El aspecto es la combinación de aviso y punto. Lo que nos dice el aviso es "¿Cuándo?" Y "¿Qué hacer?", Y el punto de contacto nos dice "¿Dónde?"

Diez, el orden de ejecución de la clase de aspecto de Aop.

10.1 El orden de ejecución se puede resolver con la anotación @order (1), cuanto menor es el número, mayor es la prioridad.

Once, springAop cambia los parámetros del método de destino y modifica el valor de retorno del método de destino (solo se aplica a around (notificación envolvente))

También puede pasar los parámetros modificados a los parámetros del método de destino para su ejecución.

    @Around("pointCut()")
    public void before(ProceedingJoinPoint joinPoint)  {
    
    
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
    
    
            System.out.println("方法的参数是"+arg);
        }

        System.out.println("环绕之前。。。");
        try {
    
    
            String proceed = (String) joinPoint.proceed();
            proceed="改变后的返回值";
            System.out.println(proceed);
        } catch (Throwable throwable) {
    
    
            throwable.printStackTrace();
        }
        System.out.println("环绕之后。。。");


    }
Código de prueba
public class Demo {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
        TestService s = (TestService) applicationContext.getBean("s");
        s.ss("String参数。。");

    }
}
Resultados de la prueba
方法的参数是String参数。。
环绕之前。。。
目标方法执行...String参数。。
改变后的返回值
环绕之后。。。

Supongo que te gusta

Origin blog.csdn.net/weixin_43983411/article/details/108125905
Recomendado
Clasificación