一、代理模式
代理对象:增强目标对象。
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......
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)