It's our wits that make us men.

Spring 使用笔记之(二) - AOP和Interceptor(拦截器)

Posted on By Freud Kang

什么是AOP

AOP(Aspect Oriented Programming)即:面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术

AOP在Spring中的术语

  • 通知(advice)
    • Before
    • After
    • After-Returning
    • After-Throwing
    • Around
  • 连接点(JointPoing)
  • 切点(PointCut)
  • 切面(Aspect)
  • 引入(Introduction)
  • 织入(Weaving)
    • 编译器 - AspectJ的做法
    • 类加载期 - AspectJ 5的LTW(Load-time weaving)的做法
    • 运行期 - Spring的做法

AOP在Spring中的支持

  • 基于代理的的经典AOP - 只能代理接口
  • 基于@AspectJ注解驱动的切面 - 只能代理类
  • 纯POJO切面
  • 注入式AspectJ切面

拦截器(Interceptor)的三种实现

  • XML配置方式

<aop:config>
	<aop:aspect ref="testInterceptor">
		<aop:pointcut expression="execution(public * com.freud.test..*.*(..))"
			id="testPointCut" />
		<aop:after method="after" pointcut-ref="testPointCut" />
		<aop:before method="before" pointcut-ref="testPointCut" />
	</aop:aspect>
</aop:config>
<bean id="testInterceptor" class="com.freud.TestInterceptor" />
package com.freud;

public class TestInterceptor {

	public void after() {
		System.out.println("After");
	}

	public void before() {
		System.out.println("before");
	}
}
  • 基于Spring定义的MethodInterceptor

  • 在Spring中共提供了四种Advice用来支持对方法调用时施加的不同行为
    • BeforeAdvice:具体接口:MethodBeforeAdvice 在目标方法调用之前调用的Advice
    • AfterAdvice:具体接口:AfterReturningAdvice 在目标方法调用并返回之后调用的Advice
    • AroundAdvice:具休接口:MethodInterceptor 在目标方法的整个执行前后有效,并且有能力控制目标方法的执行
    • ThrowsAdvice:具体接口:ThrowsAdvice 在目标方法抛出异常时调用的Advice
  • 在以上四种Advice中最为特别的就是MethodInterceptor:方法拦截器.它的特别之处在于:首先他所在的包并不Srping中的包而是:org.aopalliance.intercept包.即MethodInterceptor实现了AOP联盟接口,这一点保证了它较之其他的Advice更具有通用性,因为它可以在任何基于AOP联盟接口实现的AOP系统中使用.第二点也就是其最为突出的一点就是它所具有的其他Advice所不能匹敌的功能:在目标方法的整个执行前后有效,并且有能力控制目标方法的执行!
<bean id="testInterceptor" class="com.freud.Interceptor.TestInterceptor"></bean>
	
<aop:config >
	<!--切入点-->
	<aop:pointcut id="testPointCut" expression="execution(public * com.freud.test.*.*(..))"/>			
	
	<!-- 在该切入点使用自定义拦截器 -->
	<aop:advisor pointcut-ref="testPointCut" advice-ref="testInterceptor"/>

</aop:config>
package com.freud.test.interceptor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class TestInterceptor implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		
		//Do something before
		
		Object ret = invocation.proceed();
		
		//Do something After
		
		return ret;
	}

}
  • 纯注解方式

<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-3.0.xsd
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop.xsd">
<aop:aspectj-autoproxy />
</bean>
import org.aspectj.lang.JoinPoint;
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.aspectj.lang.annotation.Pointcut;

@Aspect
public class TestInterceptor {

	@Pointcut("execution(public * com.freud.interceptor.*.insert*(..))||execution(* com.freud.interceptor.*.add*(..))")
	public void insert() {

	}

	@AfterReturning("insert()")
	public void doAfterReturn(JoinPoint jp) {
		System.out.println("AfterReturn");
	}

	@After("insert()")
	public void doAfter(JoinPoint jp) {
		System.out.println("After");
	}

	@Before("insert()")
	public void doBefore(JoinPoint jp) {
		System.out.println("Before");
	}

	@AfterThrowing("insert()")
	public void doAfterThrowing() {
		System.out.println("AfterThrowing");
	}

	@Around("insert()")
	public void doAround() {
		System.out.println("Around");
	}

}

注意

在使用的过程中,如果Spring AOP和 Spring MVC集成,对Controller及之前的层面进行拦截,需要配置在同webcontext目录下的ApplicationContext文件中,不能配置在源目录下,否则会出现不执行拦截器的现象。

参考资料

《Spring in Action》

http://blog.csdn.net/zhangweikai966/article/details/6334366