Spring注解AspectJ操作AOP
一、被增强类
新建一个被增强的类 User,下面有个 add() 方法。
1
2
3
4
5
6
|
package com.pingguo.spring5.aopanno; public class User { public void add() { System.out.println( "add ... ..." ); } } |
二、增强类
创建增强类,用于编写增强的逻辑。
1
2
3
4
5
6
7
|
package com.pingguo.spring5.aopanno; public class UserProxy { // 前置通知 public void before() { System.out.println("before ... ..."); }}package com.pingguo.spring5.aopanno; public class UserProxy { // 前置通知 public void before() { System.out.println( "before ... ..." ); } } |
三、进行通知的配置
1. spring 配置文件中,开启扫描。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<? xml version = "1.0" encoding = "UTF-8" ?> < beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:context = "http://www.springframework.org/schema/context" xmlns:aop = "http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--开启注解扫描--> < context:component-scan base-package = "com.pingguo.spring5.aopanno" ></ context:component-scan > <!--开启 Aspect 生成代理对象--> < aop:aspectj-autoproxy ></ aop:aspectj-autoproxy > </ beans > |
这里创建了 2 个名称空间:
xmlns:context:开启注解扫描用
xmlns:aop:开启生成代理对象
2. 使用注解创建 User 和 UserProxy 对象
1
2
3
4
5
6
7
|
// 被增强类 @Component public class User { public void add() { System.out.println( "add ... ..." ); } } |
1
2
3
4
5
6
7
8
|
// 增强类 @Component public class UserProxy { // 前置通知 public void before() { System.out.println( "before ... ..." ); } } |
使用 @Component 注解。
3. 在增强类上使用注解 @Aspect
1
2
3
4
5
6
7
8
9
|
// 增强类 @Component @Aspect public class UserProxy { // 前置通知 public void before() { System.out.println( "before ... ..." ); } } |
4. spring配置,开启生成代理对象
1
2
|
<!--开启 Aspect 生成代理对象--> < aop:aspectj-autoproxy ></ aop:aspectj-autoproxy > |
在配置文件中增加配置。
5. 配置不同类型的通知
在上一篇文章中提到了 5 种不同类型的通知,在这里使用不同的注解来配置不同的类型。
(1)@Before
表示作为前置通知。
1
2
3
4
5
6
7
8
9
10
|
// 增强类 @Component @Aspect public class UserProxy { // 前置通知 @Before (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" ) public void before() { System.out.println( "before ... ..." ); } } |
@Before 注解里的 value 值就是切入点表达式,表示要对哪个类里面的哪个方法进行增强。
新建一个测试类的方法运行一下:
1
2
3
4
5
6
7
8
9
|
public class TestAop { @Test public void testAopanno() { ApplicationContext context = new ClassPathXmlApplicationContext( "bean1.xml" ); User user = context.getBean( "user" , User. class ); user.add(); } } |
运行结果:
1
2
3
|
before ... ... add ... ... Process finished with exit code 0 |
可以看出,先执行了前置增强 before() 方法,再执行了 add() 方法。
(2)@After
表示作为后置通知。而且不管有没有异常都会执行(文末示例)。
1
2
3
4
5
|
// 后置通知 @After (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" ) public void after() { System.out.println( "After ... ..." ); } |
运行结果:
1
2
3
|
add ... ... After ... ... Process finished with exit code 0 |
(3)@AfterReturning
另外,还有个注解 @AfterReturning,也是在被增强之后执行,不过可以拿到被增强方法的返回值。
修改被增强类的 add() 方法:
1
2
3
4
5
6
7
8
|
// 被增强类 @Component public class User { public String add() { System.out.println( "add ... ..." ); return "add()方法返回值" ; } } |
修改增强类:
1
2
3
4
|
@AfterReturning (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" , returning = "result" ) public void afterReturning(String result) { System.out.println( "AfterReturning ... ..." + result); } |
这里 returning = "result",result 就是定义的获取到的变量,下面可以使用。
运行测试:
1
2
3
|
add ... ... AfterReturning ... ...add()方法返回值 Process finished with exit code 0 |
(4)@Around
表示环绕通知。
1
2
3
4
5
6
7
8
|
// 环绕通知 @Around (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" ) public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println( "环绕之前 ... ..." ); // 被增强的方法执行 proceedingJoinPoint.proceed(); System.out.println( "环绕之后 ... ..." ); } |
运行结果:
1
2
3
4
|
环绕之前 ... ... add ... ... 环绕之后 ... ... Process finished with exit code 0 |
(5)@AfterThrowing
表示环绕通知。
现在让 add() 方法抛异常:
1
2
3
4
5
6
7
8
|
// 被增强类 @Component public class User { public void add() { int i = 1 / 0 ; System.out.println( "add ... ..." ); } } |
使用 @AfterThrowing:
1
2
3
4
5
|
// 异常通知 @AfterThrowing (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" ) public void afterThrowing() { System.out.println( "AfterThrowing ... ..." ); } |
运行测试:
1
2
|
AfterThrowing ... ... java.lang.ArithmeticException: / by zero |
注意,在上面提到的 @After,不管有没有异常都会执行。
1
2
3
4
5
6
7
8
9
10
|
// 异常通知 @AfterThrowing (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" ) public void afterThrowing() { System.out.println( "AfterThrowing ... ..." ); } // 后置通知 @After (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" ) public void after() { System.out.println( "After ... ..." ); } |
运行测试:
1
2
3
|
After ... ... AfterThrowing ... ... java.lang.ArithmeticException: / by zero |
四、抽取相同切入点
在上述的介绍中,发现每个通知里的切入点表达式都是一样的,那么可以进行抽取。
修改增强类,使用 @Pointcut :
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 增强类 @Component @Aspect public class UserProxy { @Pointcut (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" ) public void pointDemo() { } // 前置通知 @Before (value = "pointDemo()" ) public void before() { System.out.println( "before ... ..." ); } ... ... |
使用 @Pointcut 注解把表达式抽取出来到方法 pointDemo() 上,后续的通知里,value = "pointDemo()" 即可。
运行测试:
1
2
3
|
before ... ... add ... ... Process finished with exit code 0 |
如果需要改动表达式,只修改这一处就好。
五、多个增强类的优先级
如果有多个增强类对同一个方法进行增强,可以设置增强类的优先级。
给这 2 个增强类添加注解 @Order(1)、 @Order(2),注意,里面的数值越小,优先级越高。
新建的增强类 PersonProxy:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 新建另一个增强类 @Component @Aspect @Order ( 1 ) public class PersonProxy { @Pointcut (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" ) public void pointDemo() { } // 前置通知 @Before (value = "pointDemo()" ) public void before() { System.out.println( "PersonProxy 类的 before ... ..." ); } } |
之前的 增强类:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 增强类 @Component @Aspect @Order ( 2 ) public class UserProxy { @Pointcut (value = "execution(* com.pingguo.spring5.aopanno.User.add(..))" ) public void pointDemo() { } // 前置通知 @Before (value = "pointDemo()" ) public void before() { System.out.println( "before ... ..." ); } |
运行测试:
1
2
3
4
|
PersonProxy 类的 before ... ... before ... ... add ... ... Process finished with exit code 0 |
Order(1) 的增强了 PersonProxy 下的通知先执行。
以上就是Spring学习通过AspectJ注解方式实现AOP操作的详细内容,更多关于Spring注解AspectJ操作AOP的资料请关注服务器之家其它相关文章!
原文链接:https://blog.csdn.net/wessonlan/article/details/124812973