spring aop 样例

基于注解的AOP 方式

1.加入jar包

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

commons-logging-1.1.3.jar

spring-aop-4.1.0.RELEASE.jar

spring-aspects-4.1.0.RELEASE.jar

spring-beans-4.1.0.RELEASE.jar

spring-context-4.1.0.RELEASE.jar

spring-core-4.1.0.RELEASE.jar

spring-expression-4.1.0.RELEASE.jar

2.在配置文件中加入AOP的命名空间

3.基于注解的方式

①在配置文件中加入如下配置

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

②把横切关注点的代码抽象到切面的类中

切面首先是一个IOC中的bean,即加入@Component注解

切面还需要加入@Aspect注解

③在类中声明各种通知

@Before 前置通知,在方法执行之前执行

@After 后置通知,在方法执行之后执行

@AfterRunning 返回通知,在方法返回结果之后执行

@AfterThrowing 异常通知,在方法抛出异常之后执行

@Around 环绕通知,围绕着方法执行

③在方法中声明一个类型为JoinPoint的参数就可以访问链接细节

ArithmeticCalculator接口


1

2

3

4

5

6

7

8

9

10

11

package com.spring.aop.impl;

public interface ArithmeticCalculator {

    public int add(int i, int j);

    public int sub(int i, int j);

    public int mul(int i, int j);

    public int div(int i, int j);

}

接口实现类 ArithmeticCalculatorImpl.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

package com.spring.aop.impl;

import org.springframework.stereotype.Component;

@Component

public class ArithmeticCalculatorImpl implements ArithmeticCalculator{

    @Override

    public int add(int i, int j) {

        int result = i + j;

        return result;

    }

    @Override

    public int sub(int i, int j) {

        int result = i - j;

        return result;

    }

    @Override

    public int mul(int i, int j) {

        int result = i * j;

        return result;

    }

    @Override

    public int div(int i, int j) {

        int result = i / j;

        return result;

    }

}

切面类 LoggingAspect.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

package com.spring.aop.impl;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.AfterThrowing;

import org.aspectj.lang.annotation.Around;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.springframework.core.annotation.Order;

import org.springframework.stereotype.Component;

//指定切面的优先级,当有多个切面时,数值越小优先级越高

@Order(1)

//把这个类声明为一个切面:需要把该类放入到IOC容器中。再声明为一个切面.

@Aspect

@Component

public class LoggingAspect {

    /**

     * 声明切入点表达式,一般在该方法中不再添加其他代码。

     * 使用@Pointcut来声明切入点表达式。

     * 后面的通知直接使用方法名来引用当前的切入点表达式。

     */

    @Pointcut("execution(public int com.spring.aop.impl.ArithmeticCalculator.*(..))")

    public void declareJoinPointExpression() {}

    /**

    *前置通知,在目标方法开始之前执行。

    *@Before("execution(public int com.spring.aop.impl.ArithmeticCalculator.add(int, int))")这样写可以指定特定的方法。

     * @param joinpoint

     */

    @Before("declareJoinPointExpression()")

    //这里使用切入点表达式即可。后面的可以都改成切入点表达式。如果这个切入点表达式在别的包中,在前面加上包名和类名即可。

    public void beforeMethod(JoinPoint joinpoint) {

        String methodName = joinpoint.getSignature().getName();

        List<Object>args = Arrays.asList(joinpoint.getArgs());

        System.out.println("前置通知:The method "+ methodName +" begins with " + args);

    }

    /**

    *后置通知,在目标方法执行之后开始执行,无论目标方法是否抛出异常。

    *在后置通知中不能访问目标方法执行的结果。

     * @param joinpoint

     */

    @After("execution(public int com.spring.aop.impl.ArithmeticCalculator.*(int, int))")

    public void afterMethod(JoinPoint joinpoint) {

        String methodName = joinpoint.getSignature().getName();

        //List<Object>args = Arrays.asList(joinpoint.getArgs());  后置通知方法中可以获取到参数

        System.out.println("后置通知:The method "+ methodName +" ends ");

    }

    

    /**

    *返回通知,在方法正常结束之后执行。

    *可以访问到方法的返回值。

     * @param joinpoint

     * @param result 目标方法的返回值

     */

    @AfterReturning(value="execution(public int com.spring.aop.impl.ArithmeticCalculator.*(..))", returning="result")

    public void afterReturnning(JoinPoint joinpoint, Object result) {

        String methodName = joinpoint.getSignature().getName();

        System.out.println("返回通知:The method "+ methodName +" ends with " + result);

    }

    

    /**

    *异常通知。目标方法出现异常的时候执行,可以访问到异常对象,可以指定在出现特定异常时才执行。

    *假如把参数写成NullPointerException则只在出现空指针异常的时候执行。

     * @param joinpoint

     * @param e

     */

    @AfterThrowing(value="execution(public int com.spring.aop.impl.ArithmeticCalculator.*(..))", throwing="e")

    public void afterThrowing(JoinPoint joinpoint, Exception e) {

        String methodName = joinpoint.getSignature().getName();

        System.out.println("异常通知:The method "+ methodName +" occurs exception " + e);

    }

    

    /**

     * 环绕通知类似于动态代理的全过程,ProceedingJoinPoint类型的参数可以决定是否执行目标方法。

     * @param point 环绕通知需要携带ProceedingJoinPoint类型的参数。

     * @return 目标方法的返回值。必须有返回值。

     */

     /*不常用

    @Around("execution(public int com.spring.aop.impl.ArithmeticCalculator.*(..))")

    public Object aroundMethod(ProceedingJoinPoint point) {

        Object result = null;

        String methodName = point.getSignature().getName();

        try {

            //前置通知

            System.out.println("The method "+ methodName +" begins with " + Arrays.asList(point.getArgs()));

            //执行目标方法

            result = point.proceed();

            //翻译通知

            System.out.println("The method "+ methodName +" ends with " + result);

        } catch (Throwable e) {

            //异常通知

            System.out.println("The method "+ methodName +" occurs exception " + e);

            throw new RuntimeException(e);

        }

        //后置通知

        System.out.println("The method "+ methodName +" ends");

        return result;

    }

    */

}

applicationContext.xml


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:aop="http://www.springframework.org/schema/aop"

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

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

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

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

    <!-- 配置自动扫描包 -->

    <context:component-scan base-package="com.spring.aop.impl"></context:component-scan>

    <!-- 使AspectJ注解起作用:自动为匹配的类生产代理对象 -->

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

</beans>

Main.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

package com.spring.aop.impl;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {

    //创建spring IOC容器

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

    //从IOC容器中获取bean实例

    ArithmeticCalculator arithmeticCalculator = applicationContext.getBean(ArithmeticCalculator.class);

    int result = arithmeticCalculator.add(46);

    System.out.println(result);

    result = arithmeticCalculator.sub(46);

    System.out.println(result);

    System.out.println(result);

    result = arithmeticCalculator.mul(46);

    System.out.println(result);

    System.out.println(result);

    result = arithmeticCalculator.div(40);

    System.out.println(result);

}

}

基于配置文件的AOP 方式

引入的jar包与基于注解的方式引入的jar包相同

ArithmeticCalculator接口


1

2

3

4

5

6

7

8

9

10

11

package com.spring.aop.impl.xml;

public interface ArithmeticCalculator {

    public int add(int i, int j);

    public int sub(int i, int j);

    public int mul(int i, int j);

    public int div(int i, int j);

}

接口实现类 ArithmeticCalculatorImpl.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

package com.spring.aop.impl.xml;

public class ArithmeticCalculatorImpl implements ArithmeticCalculator{

    @Override

    public int add(int i, int j) {

        int result = i + j;

        return result;

    }

    @Override

    public int sub(int i, int j) {

        int result = i - j;

        return result;

    }

    @Override

    public int mul(int i, int j) {

        int result = i * j;

        return result;

    }

    @Override

    public int div(int i, int j) {

        int result = i / j;

        return result;

    }

}

切面类 LoggingAspect.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

package com.spring.aop.impl.xml;

import java.util.Arrays;

import java.util.List;

import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

public class LoggingAspect {

    

    public void beforeMethod(JoinPoint joinpoint) {

        String methodName = joinpoint.getSignature().getName();

        List<Object>args = Arrays.asList(joinpoint.getArgs());

        System.out.println("前置通知:The method "+ methodName +" begins with " + args);

    }

    

    public void afterMethod(JoinPoint joinpoint) {

        String methodName = joinpoint.getSignature().getName();

        //List<Object>args = Arrays.asList(joinpoint.getArgs());  后置通知方法中可以获取到参数

        System.out.println("后置通知:The method "+ methodName +" ends ");

    }

    

    public void afterReturnning(JoinPoint joinpoint, Object result) {

        String methodName = joinpoint.getSignature().getName();

        System.out.println("返回通知:The method "+ methodName +" ends with " + result);

    }

    

    public void afterThrowing(JoinPoint joinpoint, Exception e) {

        String methodName = joinpoint.getSignature().getName();

        System.out.println("异常通知:The method "+ methodName +" occurs exception " + e);

    }

    

    public Object aroundMethod(ProceedingJoinPoint point) {

        Object result = null;

        String methodName = point.getSignature().getName();

        try {

            //前置通知

            System.out.println("The method "+ methodName +" begins with " + Arrays.asList(point.getArgs()));

            //执行目标方法

            result = point.proceed();

            //翻译通知

            System.out.println("The method "+ methodName +" ends with " + result);

        catch (Throwable e) {

            //异常通知

            System.out.println("The method "+ methodName +" occurs exception " + e);

            throw new RuntimeException(e);

        }

        //后置通知

        System.out.println("The method "+ methodName +" ends");

        return result;

    }

}

切面类 ValidationAspect.java


1

2

3

4

5

6

7

8

9

10

11

12

package com.spring.aop.impl.xml;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;

public class ValidationAspect {

    public void validateArgs(JoinPoint joinPoint) {

        System.out.println("validate:" + Arrays.asList(joinPoint.getArgs()));

    }

}

applicationContext-xml.xml


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

<?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: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/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">

    <!-- 配置bean -->

    <bean id="arithmeticCalculator" class="com.spring.aop.impl.xml.ArithmeticCalculatorImpl"></bean>

    <!-- 配置切面的bean -->

    <bean id="loggingAspect" class="com.spring.aop.impl.xml.LoggingAspect"></bean>

    

    <bean id="validationAspect" class="com.spring.aop.impl.xml.ValidationAspect"></bean>

    

    <!-- 配置AOP -->

    <aop:config>

        <!-- 配置切点表达式 -->

        <aop:pointcut expression="execution(* com.spring.aop.impl.xml.ArithmeticCalculator.*(..))" id="pointcut"/>

        <!-- 配置切面及通知,使用order指定优先级 -->

        <aop:aspect ref="loggingAspect" order="1">

            <!-- 环绕通知 -->

            <!--  

                <aop:around method="aroundMethod" pointcut-ref="pointcut"/>

            -->

            <!-- 前置通知 -->

            <aop:before method="beforeMethod" pointcut-ref="pointcut"/>

            <!-- 后置通知 -->

            <aop:after method="afterMethod" pointcut-ref="pointcut"/>

            <!-- 异常通知 -->

            <aop:after-throwing method="afterThrowing"  pointcut-ref="pointcut" throwing="e"/>

            <!-- 返回通知 -->

            <aop:after-returning method="afterReturnning" pointcut-ref="pointcut" returning="result"/>

            

        </aop:aspect>

        <aop:aspect ref="validationAspect" order="2">

            <!-- 前置通知 -->

            <aop:before method="validateArgs" pointcut-ref="pointcut"/>

        </aop:aspect>

    </aop:config>

</beans>

Main.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

package com.spring.aop.impl.xml;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {

    //创建spring IOC容器

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-xml.xml");

    //从IOC容器中获取bean实例

    ArithmeticCalculator arithmeticCalculator = applicationContext.getBean(ArithmeticCalculator.class);

    int result = arithmeticCalculator.add(46);

    System.out.println(result);

    result = arithmeticCalculator.sub(46);

    System.out.println(result);

    System.out.println(result);

    result = arithmeticCalculator.mul(46);

    System.out.println(result);

    System.out.println(result);

    result = arithmeticCalculator.div(40);

    System.out.println(result);

}

}

 

时间: 2024-08-13 16:18:54

spring aop 样例的相关文章

【spring教程之中的一个】创建一个最简单的spring样例

1.首先spring的主要思想,就是依赖注入.简单来说.就是不须要手动new对象,而这些对象由spring容器统一进行管理. 2.样例结构 如上图所看到的,採用的是mavenproject. 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=&q

spring+springmvc+hibernate架构、maven分模块开发样例小项目案例

maven分模块开发样例小项目案例 spring+springmvc+hibernate架构 以用户管理做測试,分dao,sevices,web层,分模块开发測试!因时间关系.仅仅測查询成功.其它的准备在ext上做个完整的案例来的,可惜近期时间非常紧. 高级部分也没做測试,比方建私服,其它经常使用插件測试之类的,等用时间了我做个完整ext前端和maven 完整的样例出来,在分享吧. 只是眼下这些撑握了.在项目中做开发是没有问题的,其它高级部分是架构师所做的. 之前我有的资源都加上了积分,有些博友

Spring Ajax一个简单样例

配置不说了.要在前面helloworld的样例基础上弄. 相同在hello下新建ajax.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page isELIgnored ="false" %> <!DOCTYPE html PUBLIC "-//

Spring Cloud使用样例

Spring Cloud Demo 项目地址:https://github.com/hackyoMa/spring-cloud-demo 组件 基于Spring Boot 2.0.4.Spring Cloud Finchley.SR1的Spring Cloud Demo其中含有下列组件的样例: Eureka(服务注册与发现) Feign(服务消费者) Zuul(路由网关) Turbine(断路器聚合监控) Zipkin(服务链路追踪) Spring Boot Admin(服务监控中心) Spri

Spring Boot入门样例-001-Java和Maven安装配置

Spring Boot入门样例-001-Java和Maven安装配置 本文说明Java和Maven在windows下的安装和配置 前言 本Spring Boot入门样例准备工作参考: Spring Boot入门样例-001-Java和Maven安装配置 Spring Boot入门样例-003-idea 安装配置和插件 Spring Boot入门样例-005-如何运行 1. 下载 下载地址:https://www.oracle.com/technetwork/java/javase/downloa

Spring aop 小例子demo

由于最近的服务项目提供接口有一个需求,所有操作都必须检查操作的服务可用,所以感觉Aop特别适合实施.完成学习的小例子. 关于spring-Aop原理:http://m.oschina.net/blog/174838这篇文章写的非常好. 个人觉着可能上线的时候配置文件更方便一下.所以样例主要是配置文件方式 Demo文件下载地址: http://download.csdn.net/detail/ruishenh/7261121 Spring配置文件 /idle-service-impl/src/ma

我所理解的Spring AOP的基本概念

Spring AOP中的概念晦涩难懂,读官方文档更是像读天书,看了非常多样例后,写一些自己理解的一些spring的概念.要理解面向切面编程,要首先理解代理模式和动态代理模式. 如果一个OA系统中的一个功能是查看考勤信息,那么我们如果有要实现这个功能,要经历的步骤是: 1.启动日志,进行记录. 2.启动安全性的框架进行安全检验 3.验证权限 4.假设有权限,则查看考勤记录,假设无权限,则输出没有权限. 我们的目标方法是查看考勤记录,而前面运行了那么多与目标方法无关的方法. 那些与业务逻辑无关的方法

朱晔和你聊Spring系列S1E6:容易犯错的Spring AOP

标题有点标题党了,这里说的容易犯错不是Spring AOP的错,是指使用的时候容易犯错.本文会以一些例子来展开讨论AOP的使用以及使用过程中容易出错的点. 几句话说清楚AOP 有关必要术语: 切面:Aspect,有的地方也叫做方面.切面=切点+增强,表示我们在什么点切入蛋糕,切入蛋糕后我们以什么方式来增强这个点. 切点:Pointcut,类似于查询表达式,通过在连接点运行查询表达式来寻找匹配切入点,Spring AOP中默认使用AspjectJ查询表达式. 增强:Advice,有的地方也叫做通知

Spring AOP中pointcut expression表达式解析 及匹配多个条件

Pointcut 是指那些方法需要被执行"AOP",是由"Pointcut Expression"来描述的. Pointcut可以有下列方式来定义或者通过&& || 和!的方式进行组合. args() @args() execution() this() target() @target() within() @within() @annotation 其中 execution 是用的最多的,其格式为: execution(modifiers-pat