Spring AOP implements Methodmvc interceptorr 要怎么传参数进来

16516人阅读
实现MethodInterceptor
接口,在调用目标对象的方法时,就可以实现在调用方法之前、调用方法过程中、调用方法之后对其进行控制。
MethodInterceptor
接口可以实现MethodBeforeAdvice接口、AfterReturningAdvice接口、ThrowsAdvice接口这三个接口能够所能够实现的功能,但是应该谨慎使用MethodInterceptor
接口,很可能因为一时的疏忽忘记最重要的MethodInvocation而造成对目标对象方法调用失效,或者不能达到预期的设想。
关于含有Advice的三种对目标对象的方法的增强,可以参考文章
的基础上,比较MethodInterceptor
接口的实现与上面提及到的三种接口实现对目标对象方法的增强的功能效果。
我们将从应用中分离出日志切面,,将对日志的操作整合到实现MethodInterceptor
接口的类SpringMethodInterceptor中,该实现类的代码如下所示:
package org.shirdrn.spring.
import java.util.D
import org.aopalliance.intercept.MethodInterceptor
import org.aopalliance.intercept.MethodI
public class SpringMethodInterceptor implements MethodInterceptor
public Object invoke(MethodInvocation invo) throws Throwable {
Object[] object = invo.getArguments();
String date1 = (new Date()).toLocaleString();
System.out.println(&信息:[MethodInterceptor
][&+date1+&]用户 &+object[0]+& 正在尝试登录陆系统...&);
Object returnObject = invo.proceed();
String date2 = (new Date()).toLocaleString();
System.out.println(&信息:[MethodInterceptor
][&+date2+&]用户 &+object[0]+& 成功登录系统.&);
return returnO
catch(Throwable throwable){
if(object[0].equals(&Jessery&)){
throw new Exception(&信息:[MethodInterceptor
]不允许黑名单中用户 &+object[0]+& 登录系统&);
程序中,红色标示的代码行Object returnObject = invo.proceed();很关键,只有通过它来对目标对象方法调用,返回一个Object对象。
调用目标对象方法之前,可以添加跟踪日志,对方法增强,相当于使用MethodBeforeAdvice接口对方法进行增强。
调用目标对象方法之后,也可以添加跟踪日志,对方法增强,相当于使用AfterReturningAdvice接口对方法进行增强。
在执行目标对象方法的过程中,如果发生异常,可以在catch中捕获异常,相当于使用ThrowsAdvice接口对方法进行增强。
上面实现了AOP,同时要在XML中装配,配置如下所示:
&bean id=&springMethodInterceptor&
class=&org.shirdrn.spring.aop.SpringMethodInterceptor&
abstract=&false& singleton=&true& lazy-init=&default&
autowire=&default& dependency-check=&default&&
&bean id=&accountService&
class=&org.springframework.aop.framework.ProxyFactoryBean&
abstract=&false& singleton=&true& lazy-init=&default&
autowire=&default& dependency-check=&default&&
&property name=&target&&
&ref bean=&accountServiceImpl& /&
&/property&
&property name=&interceptorNames&&
&value&loginMethodBeforeAdvice&/value&
&value&loginAfterReturningAdvice&/value&
&value&loginThrowsAdvice&/value&
&value&springMethodInterceptor&/value&
&/property&
红色标示部分为对使用MethodInterceptor
对目标对象方法进行增强的配置。
测试主函数同文章
中的相同,如下所示:
package org.shirdrn.
import org.shirdrn.interf.AccountServiceI
import org.springframework.context.ApplicationC
import org.springframework.context.support.ClassPathXmlApplicationC
public class Main {
public static void main(String[] args) {
String name = &shirdrn&;
String pwd = &830119&;
ApplicationContext ctx = new ClassPathXmlApplicationContext(&applicationContext.xml&);
AccountServiceInterf asi = (AccountServiceInterf)ctx.getBean(&accountService&);
asi.login(name, pwd);
运行输出结果如下所示:
信息:[ 17:39:38]用户 shirdrn 正在尝试登录陆系统...
信息:[MethodInterceptor
][ 17:39:39]用户 shirdrn 正在尝试登录陆系统...
信息:[MethodInterceptor
][ 17:39:42]用户 shirdrn 成功登录系统.
信息:[ 17:39:42]用户 shirdrn 成功登录系统.
可见,标示为[MethodInterceptor
]的输出信息,就是MethodInterceptor
对调用目标对象方法的增强的结果。
如果我们使用非法的用户帐户登录系统:
String name = &Jessery&;
String pwd = &jessery&;
就会被MethodInterceptor
拦截器拦截,而且抛出异常,如下所示:
信息:[ 17:52:18]用户 Jessery 正在尝试登录陆系统...
信息:[MethodInterceptor
][ 17:52:18]用户 Jessery 正在尝试登录陆系统...
log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
log4j:WARN Please initialize the log4j system properly.
信息:[MethodInterceptor
][ 17:52:24]用户 Jessery 登录失败.
Exception in thread &main& java.lang.reflect.UndeclaredThrowableException
at org.shirdrn.impl.AccountServiceImpl$$EnhancerByCGLIB$$32dd7c51.login(&generated&)
at org.shirdrn.main.Main.main(Main.java:16)
用户登录过程中发生异常: Exception
Caused by: java.lang.Exception: 信息:[MethodInterceptor
]不允许黑名单中用户 Jessery 登录系统.
at org.shirdrn.spring.aop.SpringMethodInterceptor.invoke(SpringMethodInterceptor.java:27)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:51)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:53)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:623)
... 2 more
我们可以看到,使用MethodInterceptor
拦截器打印出了三项相关信息:
调用目标对象的方法之前,对其进行了增强:
信息:[MethodInterceptor
][ 17:52:18]用户 Jessery 正在尝试登录陆系统...
因为不允许非法用户Jessery登录系统,即不允许Jessery调用login方法,故在调用login方法过程中抛出了异常,并且进行了日志跟踪:
信息:[MethodInterceptor
][ 17:52:24]用户 Jessery 登录失败.
Caused by: java.lang.Exception: 信息:[MethodInterceptor
]不允许黑名单中用户 Jessery 登录系统.
使用Spring的Bean装配AOP,对于MethodBeforeAdvice接口、AfterReturningAdvice接口、ThrowsAdvice接口这三个接口在XML配置文件中配置的顺序对调用目标对象的方法没有关系。
但是如果在使用上述的基础上又使用了MethodInterceptor
,如果MethodInterceptor
配置顺序不同,就可能将对目标对象方法的调用进行拦截,使得我们预期设想的使用AfterReturningAdvice对方法调用之后增强失效。
因此,如果两类Advice同时使用,在装配的时候,在XML配置文件中,将MethodInterceptor
的配置放在其他三种Advice的后面,使得前三种Advice先起作用,最后使用MethodInterceptor
进行拦截。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:101725次
积分:1646
积分:1646
排名:第16034名
原创:66篇
转载:12篇
评论:15条
(1)(2)(1)(1)(1)(1)(3)(1)(5)(5)(2)(4)(3)(5)(2)(2)(1)(2)(7)(4)(19)(2)(5)Spring AOP 学习例子 - 为程序员服务
为程序员服务
Spring AOP 学习例子
工作忙,时间紧,不过事情再多,学习是必须的。记得以前的部门老大说过:“开发人员不可能一天到晚只有工作,肯定是需要自我学习。第一:为了更充实自己,保持进步状态。第二:为了提升技术,提高开发能力。第三:保持程序员对技术和学习的热情,工作的激情。程序员还是需要把基础打扎实,修炼自己的内功。” 所以赶紧把学习的东西总结一下,加深印象。之前有说了下AOP的原理 (/yanbincn/archive//2530377.html) 。基于代理模式,了解了jdk动态代理和cglib的用法。但是在真正的使用AOP的时候,不可能写这么厚重的方法。
Spring有两大核心,IOC和AOP。IOC在java web项目中无时无刻不在使用。然而AOP用的比较少,的确也是一般的项目用的场所不多。事务控制基本都用,但却是Spring封装的不需要我们再去实现,但Spring的AOP远不止这些,不能因为项目中没有使用,而不去学习及理解。我觉得这是作为一个java web软件开发人员必须具备的技能。业内很多将AOP应用在日志记录上,可惜我们项目没这么做,后面需要学习下。在这先把Spring AOP的基本用法,在脑子里理一边,做一次积累。
1、概念术语  
在开始之前,需要理解Spring aop 的一些基本的概念术语(总结的个人理解,并非Spring官方定义):
切面(aspect):用来切插业务方法的类。
连接点(joinpoint):是切面类和业务类的连接点,其实就是封装了业务方法的一些基本属性,作为通知的参数来解析。
通知(advice):在切面类中,声明对业务方法做额外处理的方法。
切入点(pointcut):业务类中指定的方法,作为切面切入的点。其实就是指定某个方法作为切面切的地方。
目标对象(target object):被代理对象。
AOP代理(aop proxy):代理对象。
AOP通知类型:
前置通知(before advice):在切入点之前执行。
后置通知(after returning advice):在切入点执行完成后,执行通知。
环绕通知(around advice):包围切入点,调用方法前后完成自定义行为。
异常通知(after throwing advice):在切入点抛出异常后,执行通知。
2、Spring AOP环境
要在项目中使用Spring AOP 则需要在项目中导入除了spring jar包之外,还有aspectjweaver.jar,aopalliance.jar ,asm.jar 和cglib.jar 。
好了,前提工作准备完成,Spring 提供了很多的实现AOP的方式,在学习过程中,循序渐进。进行Spring 接口方式,schema配置方式和注解的三种方式进行学习。好了废话不多说了,开始spring aop学习之旅:
3、方式一:AOP接口
利用Spring AOP接口实现AOP,主要是为了指定自定义通知来供spring AOP机制识别。主要接口:前置通知 MethodBeforeAdvice ,后置通知:AfterReturningAdvice,环绕通知:MethodInterceptor,异常通知:ThrowsAdvice 。见例子代码:
a、业务接口:
* 代理类接口,也是业务类接口&br&
* 利用接口的方式,spring aop 将默认通过jdk 动态代理来实现代理类&br&
* 不利用接口,则spring aop 将通过cglib 来实现代理类
* @author yanbin
public interface IBaseBusiness {
* 用作代理的切入点方法
* @param obj
public String delete(String obj);
* 这方法不被切面切
* @param obj
public String add(String obj);
* 这方法切不切呢?可以设置
* @param obj
public String modify(String obj);
b、业务类:
* 业务类,也是目标对象
* @author yanbin
public class BaseBusiness implements IBaseBusiness {
public String delete(String obj) {
System.out.println(&==========调用切入点:& + obj + &说:你敢删除我!===========\n&);
return obj + &:瞄~&;
public String add(String obj) {
System.out.println(&================这个方法不能被切。。。============== \n&);
return obj + &:瞄~ 嘿嘿!&;
public String modify(String obj) {
System.out.println(&=================这个也设置加入切吧====================\n&);
return obj + &:瞄改瞄啊!&;
c、通知类:
前置通知:
* 前置通知。
* @author yanbin
public class BaseBeforeAdvice implements MethodBeforeAdvice {
* method : 切入的方法 &br&
* args :切入方法的参数 &br&
* target :目标对象
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(&===========进入beforeAdvice()============ \n&);
System.out.print(&准备在& + target + &对象上用&);
System.out.print(method + &方法进行对 '&);
System.out.print(args[0] + &'进行删除!\n\n&);
System.out.println(&要进入切入点方法了 \n&);
后置通知:
* 后置通知
* @author yanbin
public class BaseAfterReturnAdvice implements AfterReturningAdvice {
* returnValue :切入点执行完方法的返回值,但不能修改 &br&
* method :切入点方法 &br&
* args :切入点方法的参数数组 &br&
* target :目标对象
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println(&==========进入afterReturning()=========== \n&);
System.out.println(&切入点方法执行完了 \n&);
System.out.print(args[0] + &在&);
System.out.print(target + &对象上被&);
System.out.print(method + &方法删除了&);
System.out.print(&只留下:& + returnValue + &\n\n&);
环绕通知:
* 环绕通知
* @author yanbin
public class BaseAroundAdvice implements MethodInterceptor {
* invocation :连接点
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println(&===========进入around环绕方法!=========== \n&);
// 调用目标方法之前执行的动作
System.out.println(&调用方法之前: 执行!\n&);
// 调用方法的参数
Object[] args = invocation.getArguments();
// 调用的方法
Method method = invocation.getMethod();
// 获取目标对象
Object target = invocation.getThis();
// 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
Object returnValue = invocation.proceed();
System.out.println(&===========结束进入around环绕方法!=========== \n&);
System.out.println(&输出:& + args[0] + &;& + method + &;& + target + &;& + returnValue + &\n&);
System.out.println(&调用方法结束:之后执行!\n&);
return returnV
异常通知:
* 异常通知,接口没有包含任何方法。通知方法自定义
* @author yanbin
public class BaseAfterThrowsAdvice implements ThrowsAdvice {
* 通知方法,需要按照这种格式书写
* @param method
可选:切入的方法
* @param args
可选:切入的方法的参数
* @param target
可选:目标对象
* @param throwable
必填 : 异常子类,出现这个异常类的子类,则会进入这个通知。
public void afterThrowing(Method method, Object[] args, Object target, Throwable throwable) {
System.out.println(&删除出错啦&);
d、定义指定切点:
* 定义一个切点,指定对应方法匹配。来供切面来针对方法进行处理&br&
* 继承NameMatchMethodPointcut类,来用方法名匹配
* @author yanbin
public class Pointcut extends NameMatchMethodPointcut {
private static final long serialVersionUID = 5944475L;
@SuppressWarnings(&rawtypes&)
public boolean matches(Method method, Class targetClass) {
// 设置单个方法匹配
this.setMappedName(&delete&);
// 设置多个方法匹配
String[] methods = { &delete&, &modify& };
//也可以用“ * ” 来做匹配符号
// this.setMappedName(&get*&);
this.setMappedNames(methods);
return super.matches(method, targetClass);
&?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:p=&http://www.springframework.org/schema/p&
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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd&
default-autowire=&byName&&
&!-- ==============================利用spring自己的aop配置================================ --&
&!-- 声明一个业务类 --&
&bean id=&baseBusiness& class=&aop.base.BaseBusiness& /&
&!-- 声明通知类 --&
&bean id=&baseBefore& class=&aop.base.advice.BaseBeforeAdvice& /&
&bean id=&baseAfterReturn& class=&aop.base.advice.BaseAfterReturnAdvice& /&
&bean id=&baseAfterThrows& class=&aop.base.advice.BaseAfterThrowsAdvice& /&
&bean id=&baseAround& class=&aop.base.advice.BaseAroundAdvice& /&
&!-- 指定切点匹配类 --&
&bean id=&pointcut& class=&aop.base.pointcut.Pointcut& /&
&!-- 包装通知,指定切点 --&
&bean id=&matchBeforeAdvisor& class=&org.springframework.aop.support.DefaultPointcutAdvisor&&
&property name=&pointcut&&
&ref bean=&pointcut& /&
&/property&
&property name=&advice&&
&ref bean=&baseBefore& /&
&/property&
&!-- 使用ProxyFactoryBean 产生代理对象 --&
&bean id=&businessProxy& class=&org.springframework.aop.framework.ProxyFactoryBean&&
&!-- 代理对象所实现的接口 ,如果有接口可以这样设置 --&
&property name=&proxyInterfaces&&
&value&aop.base.IBaseBusiness&/value&
&/property&
&!-- 设置目标对象 --&
&property name=&target&&
&ref local=&baseBusiness& /&
&/property&
&!-- 代理对象所使用的拦截器 --&
&property name=&interceptorNames&&
&value&matchBeforeAdvisor&/value&
&value&baseAfterReturn&/value&
&value&baseAround&/value&
&/property&
f、测试类:
public class Debug {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(&aop/schema_aop.xml&);
IBaseBusiness business = (IBaseBusiness ) context.getBean(&businessProxy&);
business.delete(&猫&);
g、测试结果:运行下测试类,清晰明了。由于结果呈现太长就不贴了。
具体的代码实现可以从代码注释中很容易理解 接口方式的实现。结果也可想而知,前置方法会在切入点方法之前执行,后置会在切入点方法执行之后执行,环绕则会在切入点方法执行前执行同事方法结束也会执行对应的部分。主要是调用proceed()方法来执行切入点方法。来作为环绕通知前后方法的分水岭。然后在实现的过程中,有几点却是可以细揣摩一下的。
可以看出在xml 配置 businessProxy这个bean的时候,ProxyFactoryBean类中指定了,proxyInterfaces参数。这里我把他配置了IBaseBusiness接口。因为在项目开发过程中,往往业务类都会有对应的接口,以方便利用IOC解耦。但Spring AOP却也能支持没有接口的代理。这就是为什么需要导入cglib.jar的包了。看过spring的源码,知道在目标切入对象如果有实现接口,spring会默认走jdk动态代理来实现代理类。如果没有接口,则会通过cglib来实现代理类。
这个业务类现在有 前置通知,后置通知,环绕三个通知同时作用,可能以及更多的通知进行作用。那么这些通知的执行顺序是怎么样的?就这个例子而言,同时实现了三个通知。在例子xml中,则显示执行before通知,然后执行around的前处理,执行切点方法,再执行return处理。最后执行around的后处理。经过测试,知道spring 处理顺序是按照xml配置顺序依次处理通知,以队列的方式存放前通知,以压栈的方式存放后通知。所以是前通知依次执行,后通知到切入点执行完之后,从栈里在后进先出的形式把后通知执行。
在实现过程中发现通知执行对应目标对象的整个类中的方法,如何精确到某个方法,则需要定义一个切点匹配的方式:spring提供了方法名匹配或正则方式来匹配。然后通过DefaultPointcutAdvisor来包装通知,指定切点.
利用方式一的配置起来,可见代码还是非常的厚重的,定义一个切面就要定义一个切面类,然而切面类中,就一个通知方法,着实没有必要。所以Spring提供了,依赖aspectj的schema配置和基于aspectj 注解方式。这两种方式非常简介方便使用,也是项目中普遍的使用方式。梳理之:
4、方式二:schema配置
a、业务类:
* @author yanbin
public class AspectBusiness {
public String delete(String obj) {
System.out.println(&==========调用切入点:& + obj + &说:你敢删除我!===========\n&);
return obj + &:瞄~&;
public String add(String obj) {
System.out.println(&================这个方法不能被切。。。============== \n&);
return obj + &:瞄~ 嘿嘿!&;
public String modify(String obj) {
System.out.println(&=================这个也设置加入切吧====================\n&);
return obj + &:瞄改瞄啊!&;
b、切面类:切面类中,包含了所有的通知
* 定义一个切面
* @author yanbin
public class AspectAdvice {
* 前置通知
* @param jp
public void doBefore(JoinPoint jp) {
System.out.println(&===========进入before advice============ \n&);
System.out.print(&准备在& + jp.getTarget().getClass() + &对象上用&);
System.out.print(jp.getSignature().getName() + &方法进行对 '&);
System.out.print(jp.getArgs()[0] + &'进行删除!\n\n&);
System.out.println(&要进入切入点方法了 \n&);
* 后置通知
* @param jp
* @param result
public void doAfter(JoinPoint jp, String result) {
System.out.println(&==========进入after advice=========== \n&);
System.out.println(&切入点方法执行完了 \n&);
System.out.print(jp.getArgs()[0] + &在&);
System.out.print(jp.getTarget().getClass() + &对象上被&);
System.out.print(jp.getSignature().getName() + &方法删除了&);
System.out.print(&只留下:& + result + &\n\n&);
* 环绕通知
* @param pjp
public void doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(&===========进入around环绕方法!=========== \n&);
// 调用目标方法之前执行的动作
System.out.println(&调用方法之前: 执行!\n&);
// 调用方法的参数
Object[] args = pjp.getArgs();
// 调用的方法名
String method = pjp.getSignature().getName();
// 获取目标对象
Object target = pjp.getTarget();
// 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
Object result = pjp.proceed();
System.out.println(&输出:& + args[0] + &;& + method + &;& + target + &;& + result + &\n&);
System.out.println(&调用方法结束:之后执行!\n&);
* 异常通知
* @param jp
* @param e
public void doThrow(JoinPoint jp, Throwable e) {
System.out.println(&删除出错啦&);
c、配置文件:
&?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:p=&http://www.springframework.org/schema/p&
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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd&
default-autowire=&byName&&
&!-- ==============================利用spring 利用aspectj来配置AOP================================ --&
&!-- 声明一个业务类 --&
&bean id=&aspectBusiness& class=&aop.schema.AspectBusiness& /&
&!-- 声明通知类 --&
&bean id=&aspectAdvice& class=&aop.schema.advice.AspectAdvice& /&
&aop:config&
&aop:aspect id=&businessAspect& ref=&aspectAdvice&&
&!-- 配置指定切入的对象 --&
&aop:pointcut id=&point_cut& expression=&execution(* aop.schema.*.*(..))& /&
&!-- 只匹配add方法作为切入点
&aop:pointcut id=&except_add& expression=&execution(* aop.schema.*.add(..))& /&
&!-- 前置通知 --&
&aop:before method=&doBefore& pointcut-ref=&point_cut& /&
&!-- 后置通知 returning指定返回参数 --&
&aop:after-returning method=&doAfter&
pointcut-ref=&point_cut& returning=&result& /&
&aop:around method=&doAround& pointcut-ref=&point_cut&/&
&aop:after-throwing method=&doThrow& pointcut-ref=&point_cut& throwing=&e&/&
&/aop:aspect&
&/aop:config&
d、测试类:
public class Debug {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(&aop/schema_aop.xml&);
AspectBusiness business = (AspectBusiness) context.getBean(&aspectBusiness&);
business.delete(&猫&);
5、方式三:aspectj注解
注解在项目中已经到处都是了,撇开一些优劣不提,开发的便利性和可读性是非常的方便的。用来配置Spring AOP也非常简单便利
a、业务类:
* @author yanbin
@Component
public class Business {
public String delete(String obj) {
System.out.println(&==========调用切入点:& + obj + &说:你敢删除我!===========\n&);
return obj + &:瞄~&;
public String add(String obj) {
System.out.println(&================这个方法不能被切。。。============== \n&);
return obj + &:瞄~ 嘿嘿!&;
public String modify(String obj) {
System.out.println(&=================这个也设置加入切吧====================\n&);
return obj + &:瞄改瞄啊!&;
b、切面类:
* 定义切面
* @Aspect : 标记为切面类
* @Pointcut : 指定匹配切点
* @Before : 指定前置通知,value中指定切入点匹配
* @AfterReturning :后置通知,具有可以指定返回值
* @AfterThrowing :异常通知
* @author yanbin
@Component
public class AspectAdvice {
* 指定切入点匹配表达式,注意它是以方法的形式进行声明的。
@Pointcut(&execution(* aop.annotation.*.*(..))&)
public void anyMethod() {
* 前置通知
* @param jp
@Before(value = &execution(* aop.annotation.*.*(..))&)
public void doBefore(JoinPoint jp) {
System.out.println(&===========进入before advice============ \n&);
System.out.print(&准备在& + jp.getTarget().getClass() + &对象上用&);
System.out.print(jp.getSignature().getName() + &方法进行对 '&);
System.out.print(jp.getArgs()[0] + &'进行删除!\n\n&);
System.out.println(&要进入切入点方法了 \n&);
* 后置通知
* @param jp
* @param result
@AfterReturning(value = &anyMethod()&, returning = &result&)
public void doAfter(JoinPoint jp, String result) {
System.out.println(&==========进入after advice=========== \n&);
System.out.println(&切入点方法执行完了 \n&);
System.out.print(jp.getArgs()[0] + &在&);
System.out.print(jp.getTarget().getClass() + &对象上被&);
System.out.print(jp.getSignature().getName() + &方法删除了&);
System.out.print(&只留下:& + result + &\n\n&);
* 环绕通知
* @param pjp
@Around(value = &execution(* aop.annotation.*.*(..))&)
public void doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(&===========进入around环绕方法!=========== \n&);
// 调用目标方法之前执行的动作
System.out.println(&调用方法之前: 执行!\n&);
// 调用方法的参数
Object[] args = pjp.getArgs();
// 调用的方法名
String method = pjp.getSignature().getName();
// 获取目标对象
Object target = pjp.getTarget();
// 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
Object result = pjp.proceed();
System.out.println(&输出:& + args[0] + &;& + method + &;& + target + &;& + result + &\n&);
System.out.println(&调用方法结束:之后执行!\n&);
* 异常通知
* @param jp
* @param e
@AfterThrowing(value = &execution(* aop.annotation.*.*(..))&, throwing = &e&)
public void doThrow(JoinPoint jp, Throwable e) {
System.out.println(&删除出错啦&);
&?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:p=&http://www.springframework.org/schema/p&
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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd&
default-autowire=&byName&&
&context:component-scan base-package=&aop.annotation& /&
&!-- 打开aop 注解 --&
&aop:aspectj-autoproxy /&
d、测试类:
* @author yanbin
public class Debug {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(&aop/annotation_aop.xml&);
Business business = (Business) context.getBean(&business&);
business.delete(&猫&);
您可能的代码
相关聚客文章
相关专栏文章

我要回帖

更多关于 aop interceptor 区别 的文章

 

随机推荐