spring AOP 3: Use @AspectJ para definir el punto de entrada

El uso de anotaciones para crear aspectos es una característica clave introducida por AspectJ 5. Antes de AspectJ 5, escribir aspectos de AspectJ requiere aprender una extensión del lenguaje Java, pero el modelo orientado a anotaciones de AspectJ puede convertir fácilmente cualquier clase en aspectos a través de un pequeño número de anotaciones.

AspectJ proporciona cinco anotaciones para definir notificaciones, como se muestra en la Tabla 4.2:

Tabla 4.2 Spring usa anotaciones de AspectJ para declarar métodos de notificación

Ejemplo 1: clase de audiencia: una sección para ver el rendimiento

 

package com.dxz.aop.demo7;

import org.springframework.stereotype.Component;

@Component
public class Performance {

    public void perform(){
        System.out.println("我是男一号,我正在表演");
    }
}
package com.dxz.aop.demo7;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.Configuration;

@Aspect
@Configuration
public class Audience {

    /**
     * 手机调至静音状态
     */
    @Before("execution(** com.dxz.aop.demo7.Performance.perform(..))")
    public void silenceCellPhones() {
        System.out.println("silence cell phones");
    }
    
    /**
     * 就坐
     */
    @Before("execution(** com.dxz.aop.demo7.Performance.perform(..))")
    public void takeSeats() {
        System.out.println("taking seats");
    }
    
    /**
     * 鼓掌喝彩
     */
    @AfterReturning("execution(** com.dxz.aop.demo7.Performance.perform(..))")
    public void applause() {
        System.out.println("CLAP CLAP CLAP!");
    }
    
    /**
     * 退款
     */
    @AfterReturning("execution(** com.dxz.aop.demo7.Performance.perform(..))")
    public void demandRefund() {
        System.out.println("demanding a refund");
    }
}
package com.dxz.aop.demo7;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
@Import({Audience.class})/*@Aspect可以生效,相当于Configuration类作用,都是配置类*/  
public class AppConfig {

}

Comience la clase: 

package com.dxz.aop.demo7;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test7 {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Performance outPut = (Performance) context.getBean("performance");
        outPut.perform();
    }
}

El resultado: 

 

Es posible que haya notado que a todas estas anotaciones se les asigna una expresión de corte de punto como su valor, y al mismo tiempo, las expresiones de corte de punto de los cuatro métodos son las mismas. De hecho, se pueden establecer en diferentes expresiones de corte de punto, pero aquí, esta expresión de corte de punto puede satisfacer las necesidades de todos los métodos de notificación. Esta repetición hace que las personas sientan que algo está mal. Si solo definimos este punto de corte una vez y luego lo citamos cada vez que lo necesitamos, entonces esta sería una buena solución.

Afortunadamente, podemos hacer exactamente esto: la anotación @Pointcut puede definir puntos de corte reutilizables dentro de un plano de corte @AspectJ. El siguiente programa en el Listado 4.2 muestra la nueva Audiencia, que ahora usa @Pointcut.

Ejemplo 2: la anotación @Pointcut declara expresiones de corte de punto utilizadas con frecuencia

package com.dxz.aop.demo7;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;

@Aspect
@Configuration
public class Audience2 {

    @Pointcut("execution(** com.dxz.aop.demo7.Performance.perform(..))")
    public void performance() {}
    
    /**
     * 手机调至静音状态
     */
    @Before("performance()")
    public void silenceCellPhones() {
        System.out.println("silence cell phones");
    }
    
    /**
     * 就坐
     */
    @Before("performance()")
    public void takeSeats() {
        System.out.println("taking seats");
    }
    
    /**
     * 鼓掌喝彩
     */
    @AfterReturning("performance()")
    public void applause() {
        System.out.println("CLAP CLAP CLAP!");
    }
    
    /**
     * 退款
     */
    @AfterReturning("performance()")
    public void demandRefund() {
        System.out.println("demanding a refund");
    }
}
package com.dxz.aop.demo7;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
@Import({Audience2.class})/*@Aspect可以生效,相当于Configuration类作用,都是配置类*/  
public class AppConfig {

}

Los resultados y ejemplos son igualmente efectivos

Alrededor de consejos

Ejemplo 3: utilizamos una notificación envolvente para reemplazar múltiples notificaciones previas y notificaciones posteriores diferentes

package com.dxz.aop.demo7;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;

@Aspect
@Configuration
public class Audience3 {

    @Pointcut("execution(** com.dxz.aop.demo7.Performance.perform(..))") //定义命名额切点
    public void performance() {
    }

    @Around("performance()") //环绕通知方法
    public void watchPerformance(ProceedingJoinPoint jp) {
        try {
            System.out.println("silence cell phones");
            System.out.println("taking seats");
            jp.proceed();
            System.out.println("CLAP CLAP CLAP!");
            System.out.println("demanding a refund");
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}
package com.dxz.aop.demo7;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
@Import({Audience3.class})/*@Aspect可以生效,相当于Configuration类作用,都是配置类*/  
public class AppConfig {

}

Otros sin cambios, el resultado de la operación es el mismo que el anterior

Para la palabra Introducción, personalmente creo que es más apropiado entender la introducción. El objetivo es introducir una nueva interfaz a una clase existente (uno puede preguntarse: ¿Cuál es el uso? En pocas palabras, puede transformar el objeto actual en Otro objeto, entonces, obviamente, puede llamar el método de otro objeto), vea un ejemplo para entender.  

Supongamos que ya existe una clase UserService que proporciona el servicio de guardar objetos User, pero ahora quiero agregar la función de verificar User. Solo el usuario verificado cuenta con un servicio de guardado. Se puede resolver mediante Introducción sin modificar el código de clase UserService .

Defina una interfaz llamada Skill y su clase de implementación SkillImpl. Vamos a agregar el método getSkill () de SkillImpl a otras instancias de clase

package com.dxz.aop.demo8;

public interface Person {
    public void sayIdentification();
}
package com.dxz.aop.demo8;

import org.springframework.stereotype.Component;

@Component
public class Student implements Person {

    public void sayIdentification() {
        System.out.println("hello world!");
        
    }

}

Funciones adicionales 

package com.dxz.aop.demo8;

import org.springframework.stereotype.Component;

@Component
public interface Skill {
    void getSkill(String skill);
}

package com.dxz.aop.demo8;

import org.springframework.stereotype.Component;

@Component
public class SkillImpl implements Skill {

    public void getSkill(String skill) {
        System.out.println(skill);
    }
    
}

Clase de configuración SpringAop 

package com.dxz.aop.demo8;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class AopConfig {

    // “...demo8.Perso”后面的 “+” 号,表示只要是Person及其子类都可以添加新的方法
    @DeclareParents(value = "com.dxz.aop.demo8.Person+", defaultImpl = SkillImpl.class)
    public Skill skill;
}

Clase de configuración SpringConfig 

package com.dxz.aop.demo8;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@ComponentScan
@Configuration
@EnableAspectJAutoProxy
public class SpringConfig {
}

Prueba 

package com.dxz.aop.demo8;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AopTest {

    @Autowired
    private Student student;

    @Test
    public void test(){
        Skill skill = (Skill)student; // 通过类型转换,student对象就拥有了SkillImp 类的方法
        skill.getSkill("我会英语");
        student.sayIdentification();
    }
}

 El resultado:

 

Publicados 203 artículos originales · ganado elogios 6 · vistas 4505

Supongo que te gusta

Origin blog.csdn.net/weixin_42073629/article/details/105212389
Recomendado
Clasificación