spring基于注解和XML方法的通知

一、基于注解的通知

1.创建一个User类

@Component
public class User {

    public void add(){
        System.out.println("user ... add ...");
    }

}

2.创建一个增强类

@Component
@Aspect //这个注解会创建一个代理对象
public class UserAdvice {

    //前置通知 在被增强的方法之前执行,环绕之前之后执行
    @Before("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void before(){
        System.out.println("before");
    }
	
	//后置通知 在被增强的方法之后执行,环绕之后之后执行
    @After("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void after(){
        System.out.println("after");
    }

	//返回通知 在被增强的方法将返回值返回后执行
    @AfterReturning("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning");
    }

	//异常通知 在被增强的方法发生异常后执行
    @AfterThrowing("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing");
    }

	//环绕通知,可以在方法之前执行,也可以在方法之后执行
    @Around("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("around之前");
        proceedingJoinPoint.proceed(); //执行被增强的方法
        System.out.println("around之后");
    }


}

3.在配置文件中扫描创建对象
在这里插入图片描述
4.在配置文件中扫描创建代理对象
在这里插入图片描述
5.编写测试类

public class AspectjTest {

    @Test
    public void testAspectJ(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("aspectj.xml");
        User user = applicationContext.getBean("user", User.class);
        user.add();
    }

}

输出结果:
在这里插入图片描述
相同的切入点表达式也可以进行公共抽取,例如如上的"execution(* com.wk.spring5.aspectj.User.add(…))"都是相同的。可以通过Pointcut注解抽取。其效果是一样的。

  @Pointcut("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void pointcut(){

    }

    //前置通知 在被增强的方法之前执行
    @Before(value = "pointcut()")
    public void before(){
        System.out.println("before");
    }

如果有多个增强类怎么设置优先级?
使用@Order(数字类型的值),值越小,越先执行

@Component
@Aspect
@Order(value = 0)
public class UserAdvice2 {

    @Before("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void before(){
        System.out.println("UserAdvice2的before方法执行");
    }

}
@Component
@Aspect
@Order(value = 1)
public class UserAdvice {

    /**
     * 相同的切入点可以进行抽取
     */
    @Pointcut("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void pointcut(){

    }

    //前置通知 在被增强的方法之前执行
    @Before(value = "pointcut()")
    public void before(){
        System.out.println("before");
    }

    @After("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void after(){
        System.out.println("after");
    }

    @AfterReturning("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning");
    }

    @AfterThrowing("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing");
    }

    @Around("execution(* com.wk.spring5.aspectj.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("around之前");
        proceedingJoinPoint.proceed(); //执行被增强的方法
        System.out.println("around之后");
    }


}

现在有两个增强类同时增强User中的add方法。但因为设置了优先级
所以UserAdvice2中的方法先执行。
在这里插入图片描述

二、 基于xml的通知

1.创建一个类

public class Order {

    public void order(String num){
        System.out.println("orderNum : " + num);
    }

}

2.创建增强的类

public class OrderAdvice {

    public void before(JoinPoint point){
        System.out.println("before   方法参数:" + point.getArgs()[0]);
    }

    public void after(JoinPoint point){
        System.out.println("after");
    }

    public void around(ProceedingJoinPoint point) throws Throwable{
        System.out.println("环绕之前执行");
        point.proceed();
        System.out.println("环绕之后执行");
    }

    public void afterReturn( ){
        System.out.println("afterReturn");
    }

    public void exception(){
        System.out.println("exception");
    }

}

3.在配置文件中创建这两个类的对象
在这里插入图片描述

4.在配置文件中配置切入点表达式以及切面

 <!--配置aop的增强-->
    <aop:config>
        <!--配置切入点(指明要对哪些类的哪些方法进行增强)-->
        <aop:pointcut id="myPointCut" expression="execution(* com.wk.spring5.aspectj_xml.Order.order(..))"/>

        <!--配置切面  ref:指向被增强的类 order:如果有多个增强类可以指定顺序-->
        <aop:aspect ref="orderAdvice" order="0">
            <!--用orderAdvice的before方法来做前置通知-->
            <aop:before method="before" pointcut-ref="myPointCut"></aop:before>
            <!--用orderAdvice的after方法来做后置通知-->
            <aop:after method="after" pointcut-ref="myPointCut"></aop:after>
            <!--用orderAdvice的afterReturn方法来做返回通知-->
            <aop:after-returning method="afterReturn" pointcut-ref="myPointCut"></aop:after-returning>
            <!--用orderAdvice的around方法来做环绕通知-->
            <aop:around method="around" pointcut-ref="myPointCut"></aop:around>
            <!--用orderAdvice的exception方法来做异常通知-->
            <aop:after-throwing method="exception" pointcut-ref="myPointCut"></aop:after-throwing>

        </aop:aspect>

    </aop:config>

5.编写测试类

  @Test
    public void testAspectJ_XML(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("aspectj_xml.xml");
        Order order = applicationContext.getBean("order", Order.class);
        order.order(UUID.randomUUID().toString());
    }

输出结果:
在这里插入图片描述

可以看到用xml方式同样可以完成方法增强。

如果改用纯注解方法需要单独建一个配置类。其中EnableAspectJAutoProxy注解可以创建代理对象,如果不开启这个,则无法进行增强。

@Configuration
@ComponentScan(basePackages = "com.wk.spring5.componentscan")
@EnableAspectJAutoProxy
public class SpringConfig {

}

猜你喜欢

转载自blog.csdn.net/qq_43750656/article/details/106600131