第九章 Spring5 高级应用及核心原理(二)

一、代理模式

代理对象:增强目标对象。
  
1.1 静态代理
- 定义接口
  package com.gupaoedu.service;
  
  public interface CynidService {
      public String sing(String song);
  }
  
- 创建目标对象
  package com.gupaoedu.service.impl;
  
  import com.gupaoedu.service.CynidService;
  
  public class CynidServiceImpl implements CynidService {
      public String sing(String song) {
          System.out.println("目标对象方法执行了......(Cynid 同意演唱" + song + ")");
          return "爱你";
      }
  }
   
- 创建静态代理类
  package com.gupaoedu.service;
  
  public class StaticCynidProxy implements CynidService {
  
      private CynidService cynidService;  // 需要增强的目标对象
  
      public StaticCynidProxy(CynidService cynidService) {
          this.cynidService = cynidService;
      }
  
      public String sing(String song) {
          System.out.println("目前对象执行之前的操作......(订酒店,安排行程等)");
          String res = cynidService.sing(song);
          System.out.println("目标对象执行之后的操作......(演出完之后的安排)");
          return "演唱曲目:" + res;
      }
  }
  
- 测试方法

  package com.gupaoedu.service;
  
  import com.gupaoedu.service.impl.CynidServiceImpl;
  
  public class Test {
      public static void main(String[] args) {
          // 获取目标对象
          CynidService cynidService = new CynidServiceImpl();
          // 获取代理对象 增强目标对象
          CynidService proxy = new StaticCynidProxy(cynidService);
          // 处理
          System.out.println(proxy.sing("爱你"));
      }
  }
  
执行结果:
目前对象执行之前的操作......(订酒店,安排行程等)
目标对象方法执行了......(Cynid 同意演唱爱你)
目标对象执行之后的操作......(演出完之后的安排)
演唱曲目:爱你
  
1.2 动态代理
1.2.1 JDK 动态代理
目标实现有接口,那么我们就可以使用 JDK 代理模式。
  
- 测试方法
package com.gupaoedu;

import com.gupaoedu.service.CynidService;
import com.gupaoedu.service.impl.CynidServiceImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestDyn {
    public static void main(String[] args) {
        // 获取目标对象
        final CynidService target = new CynidServiceImpl();
        // 获取代理对象
        CynidService proxy = (CynidService) Proxy.newProxyInstance(
                target.getClass().getClassLoader()  // 类加载器
                , target.getClass().getInterfaces() // 目标对象实现的接口数组
                , new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("目前对象执行之前的操作......");
                        String msg = (String)method.invoke(target, args[0]);
                        System.out.println("目标对象执行之后的操作......");
                        return "演唱一首:" + msg;
                    }
                }
        );
        System.out.println(proxy.sing("爱你"));
    }
}
  
执行结果:
目前对象执行之前的操作......
目标对象方法执行了......(Cynid 同意演唱爱你)
目标对象执行之后的操作......
演唱一首:爱你
 
1.2.2 CGLIB 动态代理
目标对象没有实现任何的接口,只能使用 CGLIB 代理,CGLIB 的本质其实的代理类继承了目标对象,并重写相关方法。
 
- 引入 CGLIB 的依赖
  <dependencies>
      <!-- https://mvnrepository.com/artifact/cglib/cglib -->
      <dependency>
          <groupId>cglib</groupId>
          <artifactId>cglib</artifactId>
          <version>2.2.2</version>
      </dependency>
  </dependencies>
  
- 创建目标对象
  package com.gupaoedu.service.impl;
  
  import com.gupaoedu.service.CynidService;
  
  public class CynidServiceImpl implements CynidService {
      public String sing(String song) {
          System.out.println("目标对象方法执行了......(Cynid 同意演唱" + song + ")");
          return "爱你";
      }
  }
  
- 创建代理类
  package com.gupaoedu.proxy;
  
  import com.gupaoedu.service.impl.JjServiceImpl;
  import net.sf.cglib.proxy.Enhancer;
  import net.sf.cglib.proxy.MethodInterceptor;
  import net.sf.cglib.proxy.MethodProxy;
  import java.lang.reflect.Method;
  
  public class CglibProxy implements MethodInterceptor {
  
      private JjServiceImpl target;
  
      public CglibProxy(JjServiceImpl target) {
          this.target = target;
      }
  
      public JjServiceImpl createProxy() {
          Enhancer enhancer = new Enhancer();
          // 指定父类
          enhancer.setSuperclass(JjServiceImpl.class);
          // 指定回调方法
          enhancer.setCallback(this);
          // 创建对象代理对象
          return (JjServiceImpl)enhancer.create();
      }
  
      /**
       * 执行代理方法
       */
      public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
          System.out.println("before......");
          String msg = (String) method.invoke(target, objects[0]);
          System.out.println("after......");
          return "演唱曲目:" + msg;
      }
  }
  
- 测试方法
  package com.gupaoedu;
  
  import com.gupaoedu.proxy.CglibProxy;
  import com.gupaoedu.service.impl.JjServiceImpl;
  
  public class TestCglib {
      public static void main(String[] args) {
          // 获取目标对象
          JjServiceImpl target = new JjServiceImpl();
          // 获取代理对象
          JjServiceImpl proxy = new CglibProxy(target).createProxy();
          System.out.println(proxy.sing("江南"));
      }
  }
  
执行结果:
before......
目标对象 Jj 执行了......江南
after......
演唱曲目:江南
  

二、Spring AOP 介绍

面向切面编程,就是将交叉业务逻辑封装成切面,利用 AOP 的功能将切面织入到主业务逻辑中。所谓交叉业务逻辑是指,通用的、与主业务逻辑无关的代码,如安全检查、事务、日志等。若不使用 AOP,则会出现代码纠缠,即交叉业务逻辑与主业务逻辑混合在一起。这样,会使主业务逻辑变的混杂不清。
| 术语          | 说明                                                         |
| ------------- | :----------------------------------------------------------- |
| 切面          | 切面泛指交叉业务逻辑。比如事务处理、日志处理就可以理解为切面。常用的切面有通知与顾问。实际就是对主业务逻辑的一种增强 |
| 织入          | 织入是指将切面代码插入到目标对象的过程。                     |
| 连接点        | 连接点指切面可以织入的位置。                                 |
| 切入点        | 切入点指切面具体织入的位置。                                 |
| 通知(Advice)  | 通知是切面的一种实现,可以完成简单织入功能(织入功能就是在这里完成的)。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。 |
| 顾问(Advisor) | 顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。 不仅指定了切入时间点,还可以指定具体的切入点 |
  
添加依赖
<dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.17.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.1</version>
    </dependency>
</dependencies>
  
2.1 AspectJ
package com.gupaoedu.service;

public interface IUserService {

    public void fun1();

    public String fun2();

    public String fun3(String userName);

}
package com.gupaoedu.service.impl;

import com.gupaoedu.service.IUserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements IUserService {

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

    public String fun2() {
        System.out.println("fun2......");
        return "fun2";
    }

    public String fun3(String userName) {
        System.out.println("fun3......");
        return "fun3";
    }
}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy	// 放开AspectJ的使用
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        bean.fun1();
    }
}
  
执行结果:(正常调用)
fun1......
  
package com.gupaoedu.aspect;

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

@Aspect     // 显示的表明当前类是一个切面类
@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("execution(* com.gupaoedu.service.impl.*.*(..))")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        bean.fun1();
    }
}
  
执行结果:
before ...... 
fun1......
 
修改切入点表达式
package com.gupaoedu.aspect;

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

@Aspect     // 显示的表明当前类是一个切面类
@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("execution(* com.gupaoedu.service.impl.*.fun2(..))")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        bean.fun1();
        bean.fun2();
    }
}
  
执行结果:fun1 之前没有输入 before ...... ,而 fun2 之前有 before ...... 。
fun1......
before ......
fun2......
  
简化提供复用
package com.gupaoedu.aspect;

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

@Aspect     // 显示的表明当前类是一个切面类
@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 提供复用
     */
    @Pointcut("execution(* com.gupaoedu.service.impl.*.fun2(..))")
    public void pointcut1(){}

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("pointcut1()")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

}
package com.gupaoedu.aspect;

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

@Aspect     // 显示的表明当前类是一个切面类
@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 提供复用
     */
    @Pointcut("execution(* com.gupaoedu.service.impl.*.fun2(..))")
    public void pointcut1(){}

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("pointcut1()")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

    /**
     * within 指定要切入的类型
     */
    @Before("within(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod02() {
        System.out.println("before ...... 02");
    }

}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        bean.fun2();
    }
}
  
执行结果:
before ......
before ...... 02
fun2......
 
package com.gupaoedu.aspect;

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

@Aspect     // 显示的表明当前类是一个切面类
@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 提供复用
     */
    @Pointcut("execution(* com.gupaoedu.service.impl.*.fun2(..))")
    public void pointcut1(){}

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("pointcut1()")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

    /**
     * within 指定要切入的类型
     */
    @Before("within(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod02() {
        System.out.println("before ...... 02");
    }

    /**
     * 在AOP中默认使用的是JDK代理模式 如果目标对象有实现接口
     * this 指的就是代理对象
     * 修改@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
     */
    @Before("this(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod03() {
        System.out.println("before ...... 03");
    }

    /**
     * target 目标对象是com.gupaoedu.service.impl.UserServiceImpl
     */
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod04() {
        System.out.println("before ...... 04");
    }

}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        bean.fun2();
    }
}
  
执行结果:
before ......
before ...... 02
before ...... 03
before ...... 04
fun2......
  
package com.gupaoedu.aspect;

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

@Aspect     // 显示的表明当前类是一个切面类
@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 提供复用
     */
    @Pointcut("execution(* com.gupaoedu.service.impl.*.fun2(..))")
    public void pointcut1(){}

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("pointcut1()")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

    /**
     * within 指定要切入的类型
     */
    @Before("within(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod02() {
        System.out.println("before ...... 02");
    }

    /**
     * 在AOP中默认使用的是JDK代理模式 如果目标对象有实现接口
     * this 指的就是代理对象
     * 修改@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
     */
    @Before("this(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod03() {
        System.out.println("before ...... 03");
    }

    /**
     * target 目标对象是com.gupaoedu.service.impl.UserServiceImpl
     */
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod04() {
        System.out.println("before ...... 04");
    }
    
    //@Before("args(String)")
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl) && args(String)")
    public void aspectMethod05() {
        System.out.println("before ...... 05");
    }

}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        //bean.fun2();
        bean.fun3("");
    }
}
  
执行结果:
before ...... 02
before ...... 03
before ...... 04
before ...... 05
fun3......
  
package com.gupaoedu.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface GpAnnotation01 {
}
package com.gupaoedu.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface GpAnnotation02 {
}
package com.gupaoedu.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface GpAnnotation03 {
}
package com.gupaoedu.aspect;

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

@Aspect     // 显示的表明当前类是一个切面类
@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 提供复用
     */
    @Pointcut("execution(* com.gupaoedu.service.impl.*.fun2(..))")
    public void pointcut1(){}

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("pointcut1()")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

    /**
     * within 指定要切入的类型
     */
    @Before("within(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod02() {
        System.out.println("before ...... 02");
    }

    /**
     * 在AOP中默认使用的是JDK代理模式 如果目标对象有实现接口
     * this 指的就是代理对象
     * 修改@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
     */
    @Before("this(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod03() {
        System.out.println("before ...... 03");
    }

    /**
     * target 目标对象是com.gupaoedu.service.impl.UserServiceImpl
     */
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod04() {
        System.out.println("before ...... 04");
    }

    //@Before("args(String)")
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl) && args(String)")
    public void aspectMethod05() {
        System.out.println("before ...... 05");
    }

    /**
     * 调用某个方法的入参被GpAnnotation01注解所修饰
     */
    @Before("@args(com.gupaoedu.annotation.GpAnnotation01)")
    public void aspectMethod06() {
        System.out.println("before ...... 06");
    }

}
package com.gupaoedu.service.impl;

import com.gupaoedu.annotation.GpAnnotation01;

@GpAnnotation01
public class Student {
}
package com.gupaoedu.service;

import com.gupaoedu.service.impl.Student;

public interface IUserService {

    public void fun1();

    public String fun2();

    public String fun3(String userName);

    public String fun4(Student student);

}
package com.gupaoedu.service.impl;

import com.gupaoedu.annotation.GpAnnotation01;
import com.gupaoedu.service.IUserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements IUserService {

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

    public String fun2() {
        System.out.println("fun2......");
        return "fun2";
    }

    //public String fun3(String userName) {
    public String fun3(@GpAnnotation01 String userName) {
        System.out.println("fun3......");
        return "fun3";
    }

    public String fun4(Student student) {
        System.out.println("fun4......");
        return "fun4";
    }
}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.Student;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        //bean.fun2();
        //bean.fun3("");
        bean.fun4(new Student());
    }
}
  
执行结果:
before ...... 02
before ...... 03
before ...... 04
before ...... 06
fun4......
  
package com.gupaoedu.service.impl;

import com.gupaoedu.annotation.GpAnnotation01;
import com.gupaoedu.annotation.GpAnnotation03;
import com.gupaoedu.service.IUserService;
import org.springframework.stereotype.Service;

@Service
@GpAnnotation03
public class UserServiceImpl implements IUserService {

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

    public String fun2() {
        System.out.println("fun2......");
        return "fun2";
    }

    //public String fun3(String userName) {
    public String fun3(@GpAnnotation01 String userName) {
        System.out.println("fun3......");
        return "fun3";
    }

    public String fun4(Student student) {
        System.out.println("fun4......");
        return "fun4";
    }
}
package com.gupaoedu.aspect;

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

@Aspect     // 显示的表明当前类是一个切面类
@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 提供复用
     */
    @Pointcut("execution(* com.gupaoedu.service.impl.*.fun2(..))")
    public void pointcut1(){}

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("pointcut1()")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

    /**
     * within 指定要切入的类型
     */
    @Before("within(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod02() {
        System.out.println("before ...... 02");
    }

    /**
     * 在AOP中默认使用的是JDK代理模式 如果目标对象有实现接口
     * this 指的就是代理对象
     * 修改@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
     */
    @Before("this(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod03() {
        System.out.println("before ...... 03");
    }

    /**
     * target 目标对象是com.gupaoedu.service.impl.UserServiceImpl
     */
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod04() {
        System.out.println("before ...... 04");
    }

    //@Before("args(String)")
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl) && args(String)")
    public void aspectMethod05() {
        System.out.println("before ...... 05");
    }

    /**
     * 调用某个方法的入参被GpAnnotation01注解所修饰
     */
    @Before("@args(com.gupaoedu.annotation.GpAnnotation01)")
    public void aspectMethod06() {
        System.out.println("before ...... 06");
    }

    /**
     * 拦截 被GpAnnotation03所修饰的类型
     */
    @Before("@within(com.gupaoedu.annotation.GpAnnotation03)")
    public void aspectMethod07() {
        System.out.println("before ...... 07");
    }
}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.Student;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        //bean.fun2();
        //bean.fun3("");
        bean.fun4(new Student());
    }
}
  
执行结果:
before ...... 02
before ...... 03
before ...... 04
before ...... 06
before ...... 07
fun4......
  
package com.gupaoedu.service.impl;

import com.gupaoedu.annotation.GpAnnotation01;
import com.gupaoedu.annotation.GpAnnotation02;
import com.gupaoedu.annotation.GpAnnotation03;
import com.gupaoedu.service.IUserService;
import org.springframework.stereotype.Service;

@Service
@GpAnnotation03
public class UserServiceImpl implements IUserService {

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

    public String fun2() {
        System.out.println("fun2......");
        return "fun2";
    }

    //public String fun3(String userName) {
    public String fun3(@GpAnnotation01 String userName) {
        System.out.println("fun3......");
        return "fun3";
    }

    @GpAnnotation02
    public String fun4(Student student) {
        System.out.println("fun4......");
        return "fun4";
    }
}

package com.gupaoedu.aspect;

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

@Aspect     // 显示的表明当前类是一个切面类
@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 提供复用
     */
    @Pointcut("execution(* com.gupaoedu.service.impl.*.fun2(..))")
    public void pointcut1(){}

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("pointcut1()")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

    /**
     * within 指定要切入的类型
     */
    @Before("within(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod02() {
        System.out.println("before ...... 02");
    }

    /**
     * 在AOP中默认使用的是JDK代理模式 如果目标对象有实现接口
     * this 指的就是代理对象
     * 修改@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
     */
    @Before("this(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod03() {
        System.out.println("before ...... 03");
    }

    /**
     * target 目标对象是com.gupaoedu.service.impl.UserServiceImpl
     */
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod04() {
        System.out.println("before ...... 04");
    }

    //@Before("args(String)")
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl) && args(String)")
    public void aspectMethod05() {
        System.out.println("before ...... 05");
    }

    /**
     * 调用某个方法的入参被GpAnnotation01注解所修饰
     */
    @Before("@args(com.gupaoedu.annotation.GpAnnotation01)")
    public void aspectMethod06() {
        System.out.println("before ...... 06");
    }

    /**
     * 拦截 被GpAnnotation03所修饰的类型
     */
    @Before("@within(com.gupaoedu.annotation.GpAnnotation03)")
    public void aspectMethod07() {
        System.out.println("before ...... 07");
    }

    @Before("@annotation(com.gupaoedu.annotation.GpAnnotation02)")
    public void aspectMethod08() {
        System.out.println("before ...... 08");
    }
}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.Student;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        //bean.fun2();
        //bean.fun3("");
        bean.fun4(new Student());
    }
}
  
执行结果:
before ...... 02
before ...... 03
before ...... 04
before ...... 06
before ...... 07
before ...... 08
fun4......
  
2.2 切入点表达式
| 表达式类型  | 说明                     |
| ----------- | ------------------------ |
| execution   | 定位到目标对象的方法上   |
| within      | 定位到具体的类型上       |
| this        | 代理对象的类型           |
| target      | 目标对象的类型           |
| args        | 参数的类型               |
| @args       | 传入的参数有被该注解修饰 |
| @within     | 类型修饰的注解           |
| @annotation | 方法修饰的注解           |
 
execution 表达式
语法:execution([访问权限类型] 返回值类型 [全限定类名] 方法名(参数名) [抛出的异常类型])
| 符合 | 含有 |
| ---- | ----------------------------------------------------- |
| * | 0 到多个符合 |
| .. | 方法参数中表示任意个参数,用在包名后表示当前包及其子包 |
| + | 用在类名后表示当前类及其子类,用在接口后表接口及其实现 |
  
实例:
execution(public * *(. .))
//指定切入点为:任意公共方法。
execution(* set *(. .))
//指定切入点为:任何一个以“set”开始的方法。
execution(* com.xyz.service.*.*(. .))
//指定切入点为:定义在service包里的任意类的任意方法。
execution(* com.xyz.service. .*.*(. .))
//指定切入点为:定义在service包或者子包里的任意类的任意方法。“..”出现在类名中时,后面必须跟“*”,表示包、子包下的所有类。
execution(* *.service.*.*(. .))
//指定只有一级包下的serivce子包下所有类(接口)中的所有方法为切入点
execution(* *. .service.*.*(. .))
//指定所有包下的serivce子包下所有类(接口)中的所有方法为切入点
   
2.3 通知类型
| 通知类型     | 说明                                                         |
| :----------- | :----------------------------------------------------------- |
| 前置通知     | 目标方法执行之前调用                                         |
| 后置通知     | 目标方法执行完成之后调用                                     |
| 环绕通知     | 目标方法执行前后都会调用方法,且能增强结果                   |
| 异常处理通知 | 目标方法出现异常调用                                         |
| 最终通知     | 无论程序执行是否正常,该通知都会执行。类似于try..catch中finally代码块 |
  
package com.gupaoedu.aspect;

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

//@Aspect     // 显示的表明当前类是一个切面类
//@Component  // 将该对象加载到IoC容器中
public class MyAspectJ01 {

    /**
     * 提供复用
     */
    @Pointcut("execution(* com.gupaoedu.service.impl.*.fun2(..))")
    public void pointcut1(){}

    /**
     * 要增强目标对象的方法
     *      指定目标对象
     *      切入点表达式
     */
    @Before("pointcut1()")
    public void aspectMethod01() {
        System.out.println("before ...... ");
    }

    /**
     * within 指定要切入的类型
     */
    @Before("within(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod02() {
        System.out.println("before ...... 02");
    }

    /**
     * 在AOP中默认使用的是JDK代理模式 如果目标对象有实现接口
     * this 指的就是代理对象
     * 修改@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
     */
    @Before("this(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod03() {
        System.out.println("before ...... 03");
    }

    /**
     * target 目标对象是com.gupaoedu.service.impl.UserServiceImpl
     */
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl)")
    public void aspectMethod04() {
        System.out.println("before ...... 04");
    }

    //@Before("args(String)")
    @Before("target(com.gupaoedu.service.impl.UserServiceImpl) && args(String)")
    public void aspectMethod05() {
        System.out.println("before ...... 05");
    }

    /**
     * 调用某个方法的入参被GpAnnotation01注解所修饰
     */
    @Before("@args(com.gupaoedu.annotation.GpAnnotation01)")
    public void aspectMethod06() {
        System.out.println("before ...... 06");
    }

    /**
     * 拦截 被GpAnnotation03所修饰的类型
     */
    @Before("@within(com.gupaoedu.annotation.GpAnnotation03)")
    public void aspectMethod07() {
        System.out.println("before ...... 07");
    }

    @Before("@annotation(com.gupaoedu.annotation.GpAnnotation02)")
    public void aspectMethod08() {
        System.out.println("before ...... 08");
    }
}
package com.gupaoedu.aspect;

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

@Component
@Aspect
public class MyAspectJ02 {

    /**
	 * 前置通知
     */
    @Before("execution(* com.gupaoedu.service.impl.*.*(..))")
    public void before() {
        System.out.println("before ... ... ");
    }

}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.Student;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        //bean.fun2();
        //bean.fun3("");
        bean.fun4(new Student());
    }
}
  
执行结果:
before ... ...
fun4......
  
package com.gupaoedu.aspect;

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

@Component
@Aspect
public class MyAspectJ02 {

    /**
     * 前置通知
     */
    @Before("execution(* com.gupaoedu.service.impl.*.*(..))")
    public void before() {
        System.out.println("before ... ... ");
    }

    /**
     * 后置通知 获取返回结果
     * @param res
     */
    @AfterReturning(value = "within(com.gupaoedu.service.impl.*)", returning = "res")
    public void afterReturning(Object res) {
        System.out.println("后置通知 ... ... " + res);
    }
}
package com.gupaoedu.service.impl;

import com.gupaoedu.annotation.GpAnnotation01;
import com.gupaoedu.annotation.GpAnnotation02;
import com.gupaoedu.annotation.GpAnnotation03;
import com.gupaoedu.service.IUserService;
import org.springframework.stereotype.Service;

@Service
@GpAnnotation03
public class UserServiceImpl implements IUserService {

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

    public String fun2() {
        System.out.println("fun2......");
        return "fun2";
    }

    //public String fun3(String userName) {
    public String fun3(@GpAnnotation01 String userName) {
        System.out.println("fun3......");
        return "fun3";
    }

    @GpAnnotation02
    public String fun4(Student student) {
        System.out.println("fun4......");
        return "fun4";
    }
}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.Student;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        //bean.fun2();
        //bean.fun3("");
        bean.fun4(new Student());
    }
}
  
执行结果:
before ... ...
fun4......
后置通知 ... ... fun4
  
package com.gupaoedu.aspect;

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.springframework.stereotype.Component;

@Component
@Aspect
public class MyAspectJ02 {

    /**
     * 前置通知
     */
    @Before("execution(* com.gupaoedu.service.impl.*.*(..))")
    public void before() {
        System.out.println("before ... ... ");
    }

    /**
     * 后置通知 获取返回结果
     * @param res
     */
    @AfterReturning(value = "within(com.gupaoedu.service.impl.*)", returning = "res")
    public void afterReturning(Object res) {
        System.out.println("后置通知 ... ... " + res);
    }

    @Around(value = "within(com.gupaoedu.service.impl.*)")
    public void around() {
        System.out.println("环绕通知 ... ... ");
    }

}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.Student;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        //bean.fun2();
        //bean.fun3("");
        bean.fun4(new Student());
    }
}
  
执行结果:
环绕通知 ... ...
后置通知 ... ... null
  
package com.gupaoedu.aspect;

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.springframework.stereotype.Component;

@Component
@Aspect
public class MyAspectJ02 {

    /**
     * 前置通知
     */
    @Before("execution(* com.gupaoedu.service.impl.*.*(..))")
    public void before() {
        System.out.println("before ... ... ");
    }

    /**
     * 后置通知 获取返回结果
     * @param res
     */
    @AfterReturning(value = "within(com.gupaoedu.service.impl.*)", returning = "res")
    public void afterReturning(Object res) {
        System.out.println("后置通知 ... ... " + res);
    }

    /**
     * 环绕通知
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around(value = "within(com.gupaoedu.service.impl.*)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("目标对象 before ... ... ");
        Object[] args = proceedingJoinPoint.getArgs();
        Object res = proceedingJoinPoint.proceed(); // 目标对象方法执行
        System.out.println("目标对象 after ... ... ");
        return res;
    }

}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.Student;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        //bean.fun2();
        //bean.fun3("");
        bean.fun4(new Student());
    }
}
  
执行结果:
目标对象 before ... ...
before ... ...
fun4......
目标对象 after ... ...
后置通知 ... ... fun4
  
package com.gupaoedu.aspect;

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

@Component
@Aspect
public class MyAspectJ02 {

    /**
     * 前置通知
     */
    @Before("execution(* com.gupaoedu.service.impl.*.*(..))")
    public void before() {
        System.out.println("before ... ... ");
    }

    /**
     * 后置通知 获取返回结果
     * @param res
     */
    @AfterReturning(value = "within(com.gupaoedu.service.impl.*)", returning = "res")
    public void afterReturning(Object res) {
        System.out.println("后置通知 ... ... " + res);
    }

    /**
     * 环绕通知
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around(value = "within(com.gupaoedu.service.impl.*)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("目标对象 before ... ... ");
        Object[] args = proceedingJoinPoint.getArgs();
        Object res = proceedingJoinPoint.proceed(); // 目标对象方法执行
        System.out.println("目标对象 after ... ... ");
        return res;
    }

    /**
     * 异常通知
     * @param ex
     */
    @AfterThrowing(value = "within(com.gupaoedu.service.impl.*)", throwing = "ex")
    public void afterThrowing(Exception ex) {
        System.out.println("异常通知产生了 ... ... " + ex);
    }
}
package com.gupaoedu.service.impl;

import com.gupaoedu.annotation.GpAnnotation01;
import com.gupaoedu.annotation.GpAnnotation02;
import com.gupaoedu.annotation.GpAnnotation03;
import com.gupaoedu.service.IUserService;
import org.springframework.stereotype.Service;

@Service
@GpAnnotation03
public class UserServiceImpl implements IUserService {

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

    public String fun2() {
        System.out.println("fun2......");
        return "fun2";
    }

    //public String fun3(String userName) {
    public String fun3(@GpAnnotation01 String userName) {
        System.out.println("fun3......");
        return "fun3";
    }

    @GpAnnotation02
    public String fun4(Student student) {
        System.out.println("fun4......" + 1/0);
        return "fun4";
    }
}
  
执行结果:
目标对象 before ... ... 
before ... ... 
异常通知产生了 ... ... java.lang.ArithmeticException: / by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.gupaoedu.service.impl.UserServiceImpl.fun4(UserServiceImpl.java:30)
	at com.gupaoedu.service.impl.UserServiceImpl$$FastClassBySpringCGLIB$$7395f8d0.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:752)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
	at com.gupaoedu.aspect.MyAspectJ02.around(MyAspectJ02.java:32)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
	at com.gupaoedu.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$4afe69b4.fun4(<generated>)
	at com.gupaoedu.JavaConfig.main(JavaConfig.java:23)
  
package com.gupaoedu.aspect;

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

@Component
@Aspect
public class MyAspectJ02 {

    /**
     * 前置通知
     */
    @Before("execution(* com.gupaoedu.service.impl.*.*(..))")
    public void before() {
        System.out.println("before ... ... ");
    }

    /**
     * 后置通知 获取返回结果
     * @param res
     */
    @AfterReturning(value = "within(com.gupaoedu.service.impl.*)", returning = "res")
    public void afterReturning(Object res) {
        System.out.println("后置通知 ... ... " + res);
    }

    /**
     * 环绕通知
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around(value = "within(com.gupaoedu.service.impl.*)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("目标对象 before ... ... ");
        Object[] args = proceedingJoinPoint.getArgs();
        Object res = proceedingJoinPoint.proceed(); // 目标对象方法执行
        System.out.println("目标对象 after ... ... ");
        return res;
    }

    /**
     * 异常通知
     * @param ex
     */
    @AfterThrowing(value = "within(com.gupaoedu.service.impl.*)", throwing = "ex")
    public void afterThrowing(Exception ex) {
        System.out.println("异常通知产生了 ... ... " + ex);
    }

    /**
     * 最终通知
     */
    @After(value = "within(com.gupaoedu.service.impl.*)")
    public void after(){
        System.out.println("最终通知...");
    }
}
package com.gupaoedu.service.impl;

import com.gupaoedu.annotation.GpAnnotation01;
import com.gupaoedu.annotation.GpAnnotation02;
import com.gupaoedu.annotation.GpAnnotation03;
import com.gupaoedu.service.IUserService;
import org.springframework.stereotype.Service;

@Service
@GpAnnotation03
public class UserServiceImpl implements IUserService {

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

    public String fun2() {
        System.out.println("fun2......");
        return "fun2";
    }

    //public String fun3(String userName) {
    public String fun3(@GpAnnotation01 String userName) {
        System.out.println("fun3......");
        return "fun3";
    }

    @GpAnnotation02
    public String fun4(Student student) {
        System.out.println("fun4......");
        //System.out.println("fun4......" + 1/0);
        return "fun4";
    }
}
package com.gupaoedu;

import com.gupaoedu.service.IUserService;
import com.gupaoedu.service.impl.Student;
import com.gupaoedu.service.impl.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)    // 修改默认的代理模式为CGLIB代理模式
@ComponentScan
public class JavaConfig {

    public static void main(String[] args) {
        ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);
        IUserService bean = ac.getBean(IUserService.class);
        //bean.fun1();
        //bean.fun2();
        //bean.fun3("");
        bean.fun4(new Student());
    }
}
  
执行结果:
目标对象 before ... ...
before ... ...
fun4......
目标对象 after ... ...
最终通知...
后置通知 ... ... fun4
  
放开异常,再次执行。
package com.gupaoedu.service.impl;

import com.gupaoedu.annotation.GpAnnotation01;
import com.gupaoedu.annotation.GpAnnotation02;
import com.gupaoedu.annotation.GpAnnotation03;
import com.gupaoedu.service.IUserService;
import org.springframework.stereotype.Service;

@Service
@GpAnnotation03
public class UserServiceImpl implements IUserService {

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

    public String fun2() {
        System.out.println("fun2......");
        return "fun2";
    }

    //public String fun3(String userName) {
    public String fun3(@GpAnnotation01 String userName) {
        System.out.println("fun3......");
        return "fun3";
    }

    @GpAnnotation02
    public String fun4(Student student) {
        //System.out.println("fun4......");
        System.out.println("fun4......" + 1/0);
        return "fun4";
    }
}
  
执行结果:
目标对象 before ... ... 
before ... ... 
最终通知...
异常通知产生了 ... ... java.lang.ArithmeticException: / by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.gupaoedu.service.impl.UserServiceImpl.fun4(UserServiceImpl.java:31)
	at com.gupaoedu.service.impl.UserServiceImpl$$FastClassBySpringCGLIB$$7395f8d0.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:752)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
	at com.gupaoedu.aspect.MyAspectJ02.around(MyAspectJ02.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:47)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
	at com.gupaoedu.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$604db0cf.fun4(<generated>)
	at com.gupaoedu.JavaConfig.main(JavaConfig.java:23)

相关推荐

  1. Spring5 高级应用核心原理

    2024-03-25 20:00:03       16 阅读
  2. Three.js 高级材质与着色器 ()

    2024-03-25 20:00:03       5 阅读
  3. Spring框架的原理应用详解(

    2024-03-25 20:00:03       7 阅读
  4. VPN技术原理(笔记)

    2024-03-25 20:00:03       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-25 20:00:03       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-25 20:00:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-25 20:00:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-25 20:00:03       20 阅读

热门阅读

  1. Python之装饰器-带参装饰器

    2024-03-25 20:00:03       21 阅读
  2. 查看nginx日志文件

    2024-03-25 20:00:03       22 阅读
  3. 3-9 枚举类代码 演示

    2024-03-25 20:00:03       18 阅读
  4. GESP C++二级认证真题 2024年3月

    2024-03-25 20:00:03       23 阅读
  5. IOS面试题编程机制 21-25

    2024-03-25 20:00:03       16 阅读
  6. 【 Vue 】辅助创建VNode的h函数

    2024-03-25 20:00:03       20 阅读