Spring AOP学习笔记(2):AOP前置通知&后置通知
2016-02-27 01:54
696 查看
一、 使用AOP之前的配置
我使用Spring来完成AOP的配置,AOP和IoC作为Spring两项最主要的特点受到良好的支持,另外使用Maven作为构建工具,在使用AOP前,先加入依赖包,完成pom.xml文件。<dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.8</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.8</version> </dependency>
二、 AOP前置通知
在上一节中已经说到,连接点由表示连接的位置和程序执行点决定,这里首先说明前置通知,即在业务逻辑之前执行的功能。先配置Spring的配置文件aop.xml:
<?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/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.spring"/> <aop:aspectj-autoproxy/> </beans><context:component-scan base-package="**"/>这就不用说了吧,基本上用过Spring的都知道,但是这里有一个问题,是我自己犯傻了,在base-package中的包表示的是一类,即,如上代码中,不仅com.spring包能被扫描到,任何前缀是它的包都能被扫描,所以我把这开始时写的很细,导致切面类没有包含进去,傻傻地还一直在找错误。
<aop:aspectj-autoproxy /> 光是看名字就知道它是什么作用,它使Aspectj的注解起作用,并且自动为满足切点的类生成在理对象,必须配置。
然后建立一个简单的业务功能,例如计算器;
package com.spring.service; import org.springframework.stereotype.Component; @Component public class Calculator { public int add(int i, int j){ return i+j; } public int sub(int i, int j){ return i-j; } public int time(int i, int j){ return i*j; } public int divide(int i, int j){ return i/j; } }然后新建一个切面类:
@Component @Aspect public class LoggingAspect { protected Logger logger = LoggerFactory.getLogger(this.getClass()); /**/ }切面类必须用@Aspect注解标明这是一个切面类,同时还需要把该切面类放到Spring的IoC容器中,所以这里用@Component注解标识,同时用slf4j来完成日志功能。
下面就是主要的内容,完成前置通知,前置通知就是在目标方法前执行,实现很简单,就是一个注释的使用。除了用注解还有xml配置方式,具体内容看下面的链接。
@Before("execution(public int com.spring.service.Calculator.*(int, int))") public void loggingBefore(JoinPoint joinPoint){ logger.info("method begin with name {} and args {}", joinPoint.getSignature().getName(), joinPoint.getArgs()); }这个@Before和junit@Before千万不能弄混了,每次自动导入时都可能出现这样的问题。
@Before中需要写的是要绑定该Advice的切点表达式。这里用的是
execution(public int com.spring.service.Calculator.*(int, int))
关于切点表达式的内容很多,这里不具体讲,但是用到的最多的就是这里的execution表达式,它用来匹配方法执行的连接点,许多其他的表达式可以在本文下面给出的链接中找。
另外可以通过JoinPoint来访问目标Target信息,包括各种标识符和参数,非常方便。
下面可以对代码进行测试一下:
ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml"); Calculator service = context.getBean(Calculator.class); int result = service.add(1,2); System.out.println(result);
得到结果如下:
三、 AOP后置通知
有前置通知,就有后置通知,其他的和前置通知没有什么区别,只是换了一个注解而已,代替@Before使用@After,后置通知在目标方法执行后 执行,无论是否发生异常都会执行。@After("execution(public int com.spring.service.Calculator.*(int, int))") public void loggingAfter(JoinPoint joinPoint){ logger.info("method end"); }测试代码类似上边如下:
ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml"); Calculator service = context.getBean(Calculator.class); int result = service.divide(1,2); System.out.println(result);结果如下:
但是又有另外的结果如下:对于这个我不是很明白,是不是后置通知在另外的线程运行,我不是很确定,如果有大神能够指出,感激不尽。
另外在发生异常时,依然能够完成通知,结果如下:
另外要注意的在后置通知中不能访问目标方法执行后返回的结果,要实现这一点要看下一节。
相关文章:
切点表达式知识和相关的例子:http://sishuok.com/forum/posts/list/281.html
类继承/接口实现时Spring AOP切入点注意事项:http://jinnianshilongnian.iteye.com/blog/1979919
Spring AOP 的xml配置方式:http://www.codeceo.com/article/java-spring-aop-config.html
涵盖所有Spring AOP知识点:http://shouce.jb51.net/spring/aop.html
相关文章推荐
- Spring AOP学习笔记(1):AOP基础知识
- Java8使用lambda表达式进行集合的遍历
- Java反射机制:方法反射的基本操作
- 矩阵乘法java代码实现
- 面向对象
- javamail 关于SSL的问题找了我一个星期之久
- JavaMail发送和接收邮件
- 观察者模式学习--使用jdk的工具类简单实现
- java项目命名规范
- Jfinal进阶系列之初体验
- java JDK8 学习笔记——第16章 整合数据库
- spring【6】(事物创建代理 BeanNameAutoProxyCreator)
- Cannot change version ...Module to 3.0 解决
- spring security oauth2
- spring项目整合mongo
- 第10课:底实战详解使用Java开发Spark程序学习笔记
- spring【7】(spring事务详解)
- NIO总结
- Java [Leetcode 136]Single Number
- struts-config.xml文件详解