spring AOP+Aspect 用来实现拦截方法。
AOP是Spring框架面向切面的编程思想,AOP采用一种称为“横切”的技术,将涉及多业务流程的通用功能抽取出来编写功能代码单独封装,形成独立的切面,在合适的时机将这些切面横向切入到业务流程指定的位置中。这样做的好处是提高了功能代码的重用性和可维护性。
一 AOP的基本概念
(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有 before,after,afterReturning,afterThrowing,around
(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使
二、通知类型介绍,常见AspectJ的注解:
- @Before – 方法执行前运行
- @After – 运行在方法返回结果后
- @AfterReturning – 运行在方法返回一个结果后,在拦截器返回结果。
- @AfterThrowing – 运行方法在抛出异常后。
- @Around – 围绕方法执行运行,结合以上这三个通知。
三、基于Aspect注解的Aop配置方式
1、pom.xml中的配置
<dependencies
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<!-- Spring Context -->
<!-- http://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<!-- aspectj -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<!-- 指定编译jar包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2、全局配置文件applicationContext.xml
<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-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
. <!-- 启用@AsjectJ支持 -->
<aop:aspectj-autoproxy />
<bean id="user" class="com.epoint.models.User">
</bean>
<bean id="logAspect" class="com.epoint.aspect.LoggingAspect"></bean>
</beans>
3、编写方法拦击类
import java.util.Arrays;
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;
@Aspect
public class LoggingAspect {
/* logBefore 方法将会在getName()方法执行前执行。 */
@Before("execution(* com.epoint.models.User.getName(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore is running!");
System.out.println("name:" + joinPoint.getSignature().getName());
System.out.println("***************");
}
/* logAfter 方法将会在getName()方法执行后执行。 */
@After("execution(* com.epoint.models.User.getName(..))")
public void logAfter(JoinPoint joinPoint) {
System.out.println("logAfter is running!");
System.out.println("name:" + joinPoint.getSignature().getName());
System.out.println("*******************");
}
/*
* logAfterReturn 方法将会在getName()方法返回结果后执行。还可以使用“returning”属性截取返回的值。
* 方法中参数需要与“returning”属性(结果)的值相同。
*/
@AfterReturning(pointcut = "execution(* com.epoint.models.User.getName(..))", returning = "result")
public void logAfterReturn(JoinPoint joinPoint, Object result) {
System.out.println("logAfterReturn is running!");
System.out.println("name:" + joinPoint.getSignature().getName());
System.out.println("returning:" + result);
System.out.println("***************");
}
/* logAfterThrow 方法将会在throwException方法执行后执行。 */
@AfterThrowing(pointcut = "execution(* com.epoint.models.User.throwException(..))", throwing = "error")
public void logAfterThrow(JoinPoint joinPoint, Throwable error) {
System.out.println("logAfterThrow is running!");
System.out.println("name:" + joinPoint.getSignature().getName());
System.out.println("Throwable:" + error);
System.out.println("***************");
}
/* logAround 方法将会在getName()方法执行前执行,必须调用joinPoint.proceed() */
@Around("execution(* com.epoint.models.User.getName(..))")
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("logAfter is running!");
System.out.println("name:" + joinPoint.getSignature().getName());
System.out.println("arguments : "
+ Arrays.toString(joinPoint.getArgs()));
System.out.println("logAround before is running");
/** 此方法控制何时拦截器返回控制到原来的getName()方法,即执行完 原来的方法。 */
joinPoint.proceed();
System.out.println("logAround after is running");
System.out.println("*******************");
}
}