Spring(基础)学习文档五(spring的aop详解)

本文深入解析Spring AOP的四个核心通知类型:前置、后置、环绕及异常通知,并介绍了如何通过自定义和预定义切入点来实现这些通知。

SpringAOP详解

要实现springaop编程,必须要知道几个概念:

1.       通知:就是交叉业务的代码,作用于目标对象中。好处是把枝节性代码和主干性代码分离开。

通知可分4种类型:

a.       前置通知:在目标方法执行之前调用。

实现MethodBeforeAdvice接口,接口方法如下:

void before(Method method,Object[] args,Object target) throws Throwable;

       这个接口为我们提供了获得目标方法,参数,目标对象的机会。注意:我们没必要在这个方法里面调用目标方法(可以通过反射调用),因为,这个接口方法结束后目标方法将调用,这才叫前置嘛(在目标方法之前)。要想终止程序的继续运行,只有抛异常或调用System.exit()

 

b.       后置通知:在目标方法执行之后调用。

实现AfterReturningAdvice接口,该接口方法如下:

void afterReturning(Object returnValue,Method method,
                    Object[] args, Object target) throws Throwable

这个方法多了一个目标方法的返回值参数。同理要结束程序流程只有抛异常和调用System.exit()方法。

      

c.       环绕通知:拦截目标方法的执行,可在该类型通知里自行调用目标方法。

实现MethodInterceptor接口,该接口在aopalliance.jar包里,这个包是aop联盟(aop编程接口,为实现aop编程接口重用)的包,可以理解成aop编程规范接口。

接口方法如下:

Object  invoke(MethodInvocation  invocation)  throws  Throwable

环绕通知和上述2个通知的区别:

1.       由于环绕通知是拦截目标方法的执行,所以在这个方法里用户可以通过invocation.proceed()方法调用目标方法,这点和MethodBeforeAdvice不同,它的目标方法总是会执行,除非抛异常或执行System.exit()方法。

2.       正常情况下这个方法返回的就是目标方法(invocation.proceed()返回的结果)的返回值,但可以在这个接口方法里改变目标方法的返回值,除非必须如此,否则最好不要这样使用。这个接口与AOP联盟的AOP框架兼容。

因为要显示的调用目标方法(invocation.proceed()),所以更推荐使用上述2种方式。

d.       异常通知:当目标方法抛出异常时调用。

实现ThrowsAdvice接口,该接口是标记接口,没有定义任何一个必须实现的方法,但实现该接口的类必须至少有一个如下形式的方法:

public void afterThrowing(Exception ex)
public void afterThrowing(RemoteException)
public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)

 

 

2.       切入点:就是插入通知的地方,由于spring是建立在方法拦截之上的,也就是说spring的切入点就是一个方法(当然是满足一定条件的方法)。

 

Spring2中方式创建切入点

a.       自定义切入点:必须实现MethodMatcher,他有3个方法:

boolean

matches(Method method, Class<?> targetClass)

boolean

isRuntime()

boolean

matches(Method method, Class<?> targetClass, Object[] args)

第一步,根据类和方法决定一个方法是否该被通知,如果满足条件返回trueisRuntime()方法被调用。isRuntime()方法被调用来决定是静态切入点还是动态切入点。

 

a.       静态切入点:通知总是被执行。isRuntime()方法返回falsematches方法将不再执行。静态切入点只在代理创建的时候执行一次,而不是运行期间,每次方法调用都执行。

运用spring自带的静态切入点:

1.       NameMatchMethodPointcut,他有2个方法

public void setMappedName(String name);

public void setMappedNames(String[] names):

当被调用方法的名字和给出的映射名字匹配时,切点才匹配。方法1是匹配一个字符串,方法2是匹配一组字符串。

下面展示如何运用该切入点实现映射:

<bean id="theAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">

        <property name="mappedName">

 

            <value>set*</value>   //匹配所有set方法

        </property>

        //或者用一组字符串去匹配,nappedNamenappedNames不能同时存在

        <property name="mappedName">

            <list>

                <value>set*</value>

                <value>get*</value>

            </list>

        </property>

 

        <property name="advice">

            <ref bean="freeAdvice"/>

        </property>

</bean>

上面这种方式是直接组装成一个Advisor了,也可拆开配置,如下:

  

<bean id="pointcutBean"

 class="org.springframework.aop.support.NameMatchMethodPointcut">
     
<property name="mappedNames"> 
        
<list> 
           
<value>set*</value> 
         
</list> 
   
</property> 
</bean>
<bean id="defaultAdvisor"      

 class="org.springframework.aop.support.DefaultPointcutAdvisor">
       
<property name="advice" ref=" beforeAdvice "/>
       
<property name="pointcut" ref="pointcutBean" />
</bean>

DefaultPointcutAdvisor类的使用很简单,他有一个 advice pointcut 属性,advice属性用来指明要使用的通知,pointcut属性用来指定切入点,我们可以通过构造子或设值注入方式来配置这个 Bean,上面选用的是set注入配置。

2.       RegexpMethodPointcut:利用正则表达式来定义切入点。RegexpMethodPointcut的详细使用方法和NameMatchMethodPointcut无多大区别,详细资料自己网上查阅。

 

 

b.       动态切入点:isRuntime()方法返回true,则执行matches方法,该方法通过参数动态判断通知是否要执行。因为每次调用目标方法时都要执行判断,所以动态切入点效率上明显更慢。

 

动态切入点还在研究中……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泡壶好茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值