1.创建被增强类

  1. package com.daijunyi.aopanno;
  2. public class User {
  3. public void add(){
  4. System.out.println("打印add方法");
  5. }
  6. }

2.创建增强类

  1. package com.daijunyi.aopanno;
  2. public class UserProxy {
  3. public void before(){
  4. System.out.println("before打印");
  5. }
  6. }

3.进行通知的注解配置
(1)在Spring配置文件中,开启注解扫描

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
  8. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
  9. <!--开启组件扫描-->
  10. <context:component-scan base-package="com.daijunyi.aopanno"></context:component-scan>
  11. </beans>

(2)使用注解创建User和UserProxy对象
image.png
image.png
(3)在增强类上添加注解@Aspect
image.png
(4)在Spring配置文件中开启生成代理对象

<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--开启组件扫描-->
    <context:component-scan base-package="com.daijunyi.aopanno"></context:component-scan>

    <!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

此步骤也可使用 配置类来实现

package com.daijunyi;

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

@Configuration
@ComponentScan(value = {"com.daijunyi.aopanno"})
@EnableAspectJAutoProxy(proxyTargetClass = true)//相当于自动开启@Aspect生成代理类
public class AopConfiguration {

}

4、配置不同类型的通知
(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

package com.daijunyi.aopanno;

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

@Component
@Aspect
public class UserProxy {

    //@Before注解表示作为前置通知
    @Before(value = "execution(* com.daijunyi.aopanno.User.add(..))")
    public void before(){
        System.out.println("before打印");
    }
}

5、测试代码

    @Test
    public void testUserProxy(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        User user = (User) context.getBean("user");
        user.add();
    }

输出结果

before打印
打印add方法

Process finished with exit code 0

6、再修改的方法多一点

package com.daijunyi.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class UserProxy {

    //@Before注解表示作为前置通知
    @Before(value = "execution(* com.daijunyi.aopanno.User.add(..))")
    public void before(){
        System.out.println("Before....");
    }

    @Around(value = "execution(* com.daijunyi.aopanno.User.add(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("环绕之前。。。");
        Object proceed = null;
        try {
            proceed = proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            System.out.println("环绕之后...");
        }
        return proceed;
    }

    @After(value = "execution(* com.daijunyi.aopanno.User.add(..))")
    public void after(){
        System.out.println("After....");
    }
    //当运行异常的时候执行
    @AfterThrowing(value = "execution(* com.daijunyi.aopanno.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing....");
    }

    //当add方法运行正常的时候执行
    @AfterReturning(value = "execution(* com.daijunyi.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("AfterReturning...");
    }
}

当代码运行正常输出结果

环绕之前。。。
Before....
打印add方法
AfterReturning...
After....
环绕之后...

Process finished with exit code 0

当运行异常的时候

环绕之前。。。
Before....
afterThrowing....
After....
java.lang.ArithmeticException: / by zero
    at com.daijunyi.aopanno.User.add(User.java:9)
    at com.daijunyi.aopanno.User$$FastClassBySpringCGLIB$$fdb63a83.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    错误省略。。。
环绕之后...

Process finished with exit code 0

从中我们可以知道,运行正常和异常唯一的区别就是正常执行会执行,AfterReturning方法,但是异常运行的时候是执行afterThrowing方法。

8、对相同切入点进行抽取。

使用注解@Pointcut进行抽取

package com.daijunyi.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class UserProxy {

    //相同切入点抽取
    @Pointcut(value = "execution(* com.daijunyi.aopanno.User.add(..))")
    public void point(){

    }

    //@Before注解表示作为前置通知
    @Before(value = "point()")
    public void before(){
        System.out.println("Before....");
    }

    @Around(value = "point()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("环绕之前。。。");
        Object proceed = null;
        try {
            proceed = proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            System.out.println("环绕之后...");
        }
        return proceed;
    }

    @After(value = "point()")
    public void after(){
        System.out.println("After....");
    }

    @AfterThrowing(value = "point()")
    public void afterThrowing(){
        System.out.println("afterThrowing....");
    }

    @AfterReturning(value = "point()")
    public void afterReturning(){
        System.out.println("AfterReturning...");
    }
}

9、有多个增强类多同一个方法进行增强,设置增强类优先级

当我们有多个增强类的时候,可以使用注解@Order(数字)来设置方法优先级,数值越小优先级越前

package com.daijunyi.aopanno;


import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(1)
public class PersonProxy {

    @Pointcut(value = "execution(* com.daijunyi.aopanno.User.add(..))")
    public void point(){

    }

    @After(value = "point()")
    public void after(){
        System.out.println("PersonProxy.after......");
    }

    @Before(value = "point()")
    public void before(){
        System.out.println("PersonProxy.before......");
    }

}
@Component
@Aspect
@Order(2)
public class UserProxy {
PersonProxy.before......
环绕之前。。。
Before....
打印add方法
AfterReturning...
After....
环绕之后...
PersonProxy.after......

Process finished with exit code 0