第九章 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)
Spring框架是主要的开源应用程序开发框架,它使得Java/J2EE开发更容易、效率更高。本书不仅向读者展示了Spring能做什么?而且揭示了Spring完成这些功能的原理,解释其功能和动机,以帮助读者使用该框架的所有部分来开发成功的应用程序。本书涵盖Spring的所有特性,并且演示了如何将其构成一个连贯的整体,帮助读者理解Spring方法的基本原理、何时使用Sping以及如何效仿最佳实践。所有这些都以完整的样本应用程序来举例说明。读完本书,读者将能够有效地在各种应用(从简单的web应用程序到复杂的企业级应用程序)使用Spring。 作者:()约翰逊 译者:蒋培 Rod Johnsn是Spring框架的创始人,并且是Java和J2EE领域的著名专家。   Rod获悉民大学博士学位。他具有C/C++开发背景,从Java和J2EE发布以来就作为开发者、休系结构设计者和顾问涉足了Java和J2EE领域。   他撰写了两本最普及并最有影响力的J2EE书籍:《Expert One-on-one J2EE Design and Deuelo Pment》(Wrox,2002),和《J2EE without EJB》(Wrox,2004.与Juergen Hoelle合著)。这两本书在“敏捷J2EE的兴起和心变过度复杂的传统J2EE体系结构方面都起了得要作用。   Rod是Spring框架的共同领导之一。他的发言很受欢迎,并且经常出现在美国、欧洲和亚洲举行的Java重要活动中。了是一些JSR的专家组的成员,为Java社区发展计划(Java Community Process,JCP)EBTL。   他还具有在银行和金融、保险、软件、媒体等领域从事顾问的广泛经验。他是Interface21的CEO,Interface21是一家致力于提供专家级J2EE和Spring框架服务的咨询公司。他各极参与客户项目和Spring开发
Spring 5 Design Patterns is for all Java developers who want to learn Spring for the enterprise application. Therefore, enterprise Java developers will find it particularly useful in the understanding of design patterns used by the Spring Framework and how it solves common design problems in the enterprise application, and they will fully appreciate the examples presented in this book. Before reading this book, readers should have basic knowledge of Core Java, JSP, Servlet, and XML. Spring 5 Framework is newly launched by Pivotal with reactive programming. Spring 5 introduces many new features and enhancements from its previous version. We will discuss all this in the book. Spring 5 Design Patterns will give you in-depth insight about the Spring Framework. The great part of today's Spring Framework is that all companies have already taken it as a primary framework for development of the enterprise application. For Spring, no external enterprise server is needed to start working with it. The goals of writing this book are to discuss all design patterns used behind the Spring Framework and how they are implemented in the Spring Framework. Here, the author has also given you some best practices that must be used in the design and development of the application. The book contains 12 chapters that cover everything from the basics to more complex design pattern such as reactive programming. Spring 5 Design Patterns is divided into three sections. The first section introduces you to the essentials of the design patterns and the Spring Framework. The second section steps behind the front end and shows where Spring fits in the back end of an application. The third section expands on this by showing how to build web applications with Spring and introducing a new feature of the Spring 5 reactive programming. This part also shows how to handle concurrency in the enterprise application.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸之间不太闲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值