一起学Spring之注解和Schema方式实现AOP

本文内容纲要:

- 概述

- 实现AOP的三种方式:

- 通过注解方式实现AOP

- 步骤如下:

- 1. 定义一个类,并在类上面增加@Aspect注解,表名此类为切面通知类。

- 2. 前置通知函数

- 3. 后置通知

- 4. 异常通知

- 5. 环绕通知

- 6. 最终通知

- 7. 除了上述注解之外,还需要在Sping容器中,配置对注解的支持和AOP的自动扫描。

- 通过Schema方式实现AOP

- 1. 定义一个普通的类,分别实现各种功能的通知,参数和注解方式的一致。

- 2. 在Spring容器中配置

- 备注

概述

在上一篇,我们了解了通过实现接口和XML配置的方式来实现AOP,在实现注解方式AOP之前,先了解一下AspectJ。AspectJ是一个面向切面的框架,它扩展了Java语言,定义了AOP语法,能够在编译时实现代码的注入。Spring通过集成ApsectJ实现了以注解方式定义通知类,大大减少了配置文件的工作量。本文主要讲解通过注解方式和Schema方式实现AOP编程,仅供学习分享使用,如有不足之处,还请指正。

实现AOP的三种方式:

  1. 通过实现相应接口,并配置Xml进行实现,可以参考上一篇。
  2. 通过注解方式实现。
  3. 通过Schema的方式实现。

通过注解方式实现AOP

@Aspect 放在类的上面,表示这个类在Spring容器中是一个切点注入类。

@Component("logAnnotation") 表示此类是一个Bean,在Spring Ioc容器里面进行注入。

步骤如下:

1. 定义一个类,并在类上面增加@Aspect注解,表名此类为切面通知类。

如下所示:

1 package com.hex.second;

2

3 import org.aspectj.lang.JoinPoint;

4 import org.aspectj.lang.ProceedingJoinPoint;

5 import org.aspectj.lang.annotation.AfterReturning;

6 import org.aspectj.lang.annotation.AfterThrowing;

7 import org.aspectj.lang.annotation.Around;

8 import org.aspectj.lang.annotation.Aspect;

9 import org.aspectj.lang.annotation.Before;

10 import org.springframework.stereotype.Component;

11

12 /**

13 * @Aspect:声明类为一个通知类

14 * @Component("logAnnotation"):通过注解方法生成一个Bean,但是需要配置注解的支持

15 * 通过注解的方式声明通知

16 * @author Administrator

17 *

18 */

19 @Component("logAnnotation")

20 @Aspect

21 public class LogAspectAnnotation {

22

23 }

2. 前置通知函数

@Before("execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))") 表示前置通知,用两个参数,默认为value值,指示切入点,告诉Spring在哪些地方进行注入。

JoinPoint 可以获取切入点的所有内容,包括目标对象,函数名称,参数,返回值等等。如下所示:

1 /**

2 * 前置通知,@Before的参数为目标通知类的表达式

3 * JoinPoint 用来获取目标函数的参数及对象等信息

4 */

5 @Before("execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))")

6 public void MyBefore(JoinPoint jp){

7 System.out.println("我是注解方式的前置通知");

8 System.out.println("method="+jp.getSignature().getName()+",args数量="+jp.getArgs().length+",target="+jp.getTarget());

9 }

3. 后置通知

@AfterReturning(pointcut = "execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))",returning="returningValue") 表示后置通知,其中value和poingcut都表示切入点,功能一样。returning表示定义目标函数的返回值。如下所示:

1 /**

2 * 功能:后置通知

3 * 注解形式实现AOP通知时,参数不能随便写,否则和目标函数对应不上,会报错

4 * @param jp :切入点目标对象

5 * @param returningValue 返回值

6 */

7 @AfterReturning(pointcut = "execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))",returning="returningValue")

8 public void MyAfterReturning(JoinPoint jp,Object returningValue){

9 System.out.println("我是注解方式的后置通知");

10 System.out.println("返回值是:"+returningValue);

11 }

4. 异常通知

@AfterThrowing(pointcut="execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))",throwing="e") 表示异常通知,其中trowing表示将抛出异常绑定到参数中。当切入函数抛出异常时将会触发,如下所示:

1 /**

2 * 异常通知

3 */

4 @AfterThrowing(pointcut="execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))",throwing="e")

5 public void MyAfterThrow(JoinPoint jp,Throwable e){

6 System.out.println("我是注解方式的异常通知");

7 }

5. 环绕通知

@Around(value="execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))") 环绕通知功能最全面,可以实现其他几种,其中参数使用ProceedingJoinPoint,是JoinPoint的子类。

1 /**

2 * 环绕通知

3 * @param jp 才用的是JoinPoint的子类

4 */

5 @Around(value="execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))")

6 public void MyAround(ProceedingJoinPoint jp){

7 Object obj = null;

8 try {

9

10 // 前置通知

11 System.out.println("注解环绕实现前置通知。。。");

12 System.out.println("环绕通知:target="+jp.getTarget()+",method="+jp.getSignature().getName()+",args="+jp.getArgs().length);

13 // 控制目标方法的执行 obj表示目标方法的返回值,表示执行addStudent(student)方法

14 //此方法控制目标方法的执行,如果不写此方法,则目标方法不会执行,此方法前的是前置通知,此方法后的是后置通知

15 obj = jp.proceed();

16 // 后置通知

17 System.out.println("注解环绕实现后置通知。。。");

18 } catch (Throwable e) {

19 // 异常通知

20 System.out.println("注解环绕实现异常通知。。。");

21 }finally{

22 //最终通知

23 System.out.println("注解环绕实现最终通知。。。");

24 }

25 }

6. 最终通知

@After("execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))") 表示最终通知,不管是否抛出异常,都会得到执行,类似于finally。如下所示:

1 /**

2 * 最终通知,@After的参数为目标通知类的表达式

3 * JoinPoint 用来获取目标函数的参数及对象等信息

4 */

5 @After("execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))")

6 public void MyAfter(JoinPoint jp){

7 System.out.println("我是注解方式最终通知");

8 System.out.println("method="+jp.getSignature().getName()+",args数量="+jp.getArgs().length+",target="+jp.getTarget());

9 }

7. 除了上述注解之外,还需要在Sping容器中,配置对注解的支持和AOP的自动扫描。

如下所示:

1 <?xml version="1.0" encoding="UTF-8"?>

2 <beans xmlns="http://www.springframework.org/schema/beans"

3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4 xmlns:p="http://www.springframework.org/schema/p"

5 xmlns:aop="http://www.springframework.org/schema/aop"

6 xmlns:context="http://www.springframework.org/schema/context"

7 xsi:schemaLocation="http://www.springframework.org/schema/beans

8 http://www.springframework.org/schema/beans/spring-beans.xsd

9 http://www.springframework.org/schema/aop

10 http://www.springframework.org/schema/aop/spring-aop.xsd

11 http://www.springframework.org/schema/context

12 http://www.springframework.org/schema/context/spring-context.xsd">

13

14 <!-- 服务类 -->

15 <bean id="studentService" class="com.hex.second.StudentServiceImpl">

16

17 </bean>

18 <!-- 将addStudent和通知进行关联 -->

19 <!-- 配置对注解方式AOP的支持 -->

20 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

21 <!-- 配置对注解的扫描 -->

22 <context:component-scan base-package="com.hex.second"></context:component-scan>

23 </beans>

通过Schema方式实现AOP

通过Schema方式实现步骤如下:

1. 定义一个普通的类,分别实现各种功能的通知,参数和注解方式的一致。

如下所示:

ImageImage

1 package com.hex.second;

2

3 import org.aspectj.lang.JoinPoint;

4 import org.aspectj.lang.ProceedingJoinPoint;

5

6 /**

7 * 通过Schema配置的方式实现通知

8 * @author Administrator

9 *

10 */

11 public class LogAspectSchema {

12 /**

13 * 前置通知,@Before的参数为目标通知类的表达式

14 * JoinPoint 用来获取目标函数的参数及对象等信息

15 */

16 public void MyBefore(JoinPoint jp){

17 System.out.println("我是Schema方式的前置通知");

18 System.out.println("method="+jp.getSignature().getName()+",args数量="+jp.getArgs().length+",target="+jp.getTarget());

19 }

20

21 /**

22 * 功能:后置通知

23 * Schema形式实现AOP通知时,参数不能随便写,否则和目标函数对应不上,会报错

24 * @param jp :切入点目标对象

25 * @param returningValue 返回值

26 */

27 public void MyAfterReturning(JoinPoint jp,Object returningValue){

28 System.out.println("我是Schema方式的后置通知");

29 System.out.println("返回值是:"+returningValue);

30 }

31

32 /**

33 * 异常通知

34 */

35 public void MyAfterThrow(JoinPoint jp ,Throwable ex){

36 System.out.println("我是Schema方式的异常通知");

37 System.out.println("ex:"+ex.getMessage());

38 }

39

40 /**

41 * 环绕通知

42 * @param jp 才用的是JoinPoint的子类

43 */

44 public void MyAround(ProceedingJoinPoint jp){

45 Object obj = null;

46 try {

47

48 // 前置通知

49 System.out.println("Schema环绕实现前置通知。。。");

50 System.out.println("Schema环绕通知:target="+jp.getTarget()+",method="+jp.getThis()+",args="+jp.getArgs().length);

51 // 控制目标方法的执行 obj表示目标方法的返回值,表示执行addStudent(student)方法

52 //此方法控制目标方法的执行,如果不写此方法,则目标方法不会执行,此方法前的是前置通知,此方法后的是后置通知

53 obj = jp.proceed();

54 // 后置通知

55 System.out.println("Schema环绕实现后置通知。。。");

56 } catch (Throwable e) {

57 // 异常通知

58 System.out.println("Schema环绕实现异常通知。。。");

59 }finally{

60 //最终通知

61 System.out.println("Schema环绕实现最终通知。。。");

62 }

63 }

64

65 /**

66 * 最终通知

67 * @param jp

68 */

69 public void MyAfter(JoinPoint jp){

70 System.out.println("我是Schema方式的最终通知");

71 }

72 }

View Code

2. 在Spring容器中配置

首先将通知类注入到Spring IOC容器中,然后配置aop:config将业务类和切面类关联起来。如下所示:

ImageImage

1 <?xml version="1.0" encoding="UTF-8"?>

2 <beans xmlns="http://www.springframework.org/schema/beans"

3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4 xmlns:p="http://www.springframework.org/schema/p"

5 xmlns:aop="http://www.springframework.org/schema/aop"

6 xmlns:context="http://www.springframework.org/schema/context"

7 xsi:schemaLocation="http://www.springframework.org/schema/beans

8 http://www.springframework.org/schema/beans/spring-beans.xsd

9 http://www.springframework.org/schema/aop

10 http://www.springframework.org/schema/aop/spring-aop.xsd

11 http://www.springframework.org/schema/context

12 http://www.springframework.org/schema/context/spring-context.xsd">

13

14 <!-- 服务类 -->

15 <bean id="studentService" class="com.hex.second.StudentServiceImpl">

16

17 </bean>

18 <bean id="logSchema" class="com.hex.second.LogAspectSchema"></bean>

19 <aop:config>

20 <!-- 配置切入点 -->

21 <aop:pointcut expression="execution(public void com.hex.second.StudentServiceImpl.deleteStudent(int)) or execution(public void com.hex.second.StudentServiceImpl.addStudent(com.hex.second.Student))" id="pc"/>

22 <aop:aspect ref="logSchema">

23 <!-- 通过Schema实现的通知 -->

24 <aop:before method="MyBefore" pointcut-ref="pc"/>

25 <aop:after-returning method="MyAfterReturning" pointcut-ref="pc" returning="returningValue"/>

26 <aop:after-throwing method="MyAfterThrow" pointcut-ref="pc" throwing="ex" />

27 <aop:around method="MyAround" pointcut-ref="pc"/>

28 <aop:after method="MyAfter" pointcut-ref="pc"/>

29 </aop:aspect>

30 </aop:config>

31 </beans>

View Code

备注

假如你不够快乐

也不要把眉头深锁

人生本来短暂

为什么 还要栽培苦涩

打开尘封的门窗

让阳光雨露洒遍每个角落

走向生命的原野

让风儿熨平前额

博大可以稀释忧愁

深色能够覆盖浅色

本文内容总结:概述,实现AOP的三种方式:,通过注解方式实现AOP,步骤如下:,1. 定义一个类,并在类上面增加@Aspect注解,表名此类为切面通知类。,2. 前置通知函数,3. 后置通知,4. 异常通知,5. 环绕通知,6. 最终通知,7. 除了上述注解之外,还需要在Sping容器中,配置对注解的支持和AOP的自动扫描。,通过Schema方式实现AOP,1. 定义一个普通的类,分别实现各种功能的通知,参数和注解方式的一致。,2. 在Spring容器中配置,备注,

原文链接:https://www.cnblogs.com/hsiang/p/11747309.html

以上是 一起学Spring之注解和Schema方式实现AOP 的全部内容, 来源链接: utcz.com/z/296908.html

回到顶部