Spring AOP 4个Advice和动态代理

Spring AOP 提供的四个Advice
spring面向切面编程,主要就是基于动态代理。单独抽象出非业务的功能,服务于某些业务方法。
Spring提供了四种很实用的Advice,
分别为:Before Advice, After Returning Advice, Around Advice, After throwing Advice。
都是方法级别的,就是在某个方法执行前后插入一些非业务的操作,如打日志或者判断权限等。


对于这四种advice的实现,spring都提供了三种方法,分别为基于接口、基于xml和基于annotation(注释)。
Before Advice会在目标对象的方法执行之前被调用;
After Advice会在目标方法执行之后被调用;
Around Advice则可以在目标方法执行前后同时加上相关服务;
Throw Advice是在异常发生后执行某些操作。


1.基于接口的Advice

这个就需要自定义的 Aspect 实现Spring接口。
BeforeAdvice 需要实现 org.springframework.aop.MethodBeforeAdvice  接口:

/**
 * Advice invoked before a method is invoked. Such advices cannot
 * prevent the method call proceeding, unless they throw a Throwable.
 *
 * @see AfterReturningAdvice
 * @see ThrowsAdvice
 *
 * @author Rod Johnson
 */
public interface MethodBeforeAdvice extends BeforeAdvice {


/**
* Callback before a given method is invoked.
* @param method method being invoked
* @param args arguments to the method
* @param target target of the method invocation. May be {@code null}.
* @throws Throwable if this object wishes to abort the call.
* Any exception thrown will be returned to the caller if it's
* allowed by the method signature. Otherwise the exception
* will be wrapped as a runtime exception.
*/
void before(Method method, Object[] args, Object target) throws Throwable;


}




After Advice实现org.springframework.aop.AfterReturningAdvice 接口:

/**
 * After returning advice is invoked only on normal method return, not if an
 * exception is thrown. Such advice can see the return value, but cannot change it.
 *
 * @author Rod Johnson
 * @see MethodBeforeAdvice
 * @see ThrowsAdvice
 */
public interface AfterReturningAdvice extends AfterAdvice {


/**
* Callback after a given method successfully returned.
* @param returnValue the value returned by the method, if any
* @param method method being invoked
* @param args arguments to the method
* @param target target of the method invocation. May be {@code null}.
* @throws Throwable if this object wishes to abort the call.
* Any exception thrown will be returned to the caller if it's
* allowed by the method signature. Otherwise the exception
* will be wrapped as a runtime exception.
*/
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;


}



Around Advice需要实现org.aopalliance.intercept.MethodInterceptor 接口:
package org.aopalliance.intercept;


/**
 * Intercepts calls on an interface on its way to the target. These
 * are nested "on top" of the target.
 *
 * <p>The user should implement the {@link #invoke(MethodInvocation)}
 * method to modify the original behavior. E.g. the following class
 * implements a tracing interceptor (traces all the calls on the
 * intercepted method(s)):
 *
 * <pre class=code>
 * class TracingInterceptor implements MethodInterceptor {
 *   Object invoke(MethodInvocation i) throws Throwable {
 *     System.out.println("method "+i.getMethod()+" is called on "+
 *                        i.getThis()+" with args "+i.getArguments());
 *     Object ret=i.proceed();
 *     System.out.println("method "+i.getMethod()+" returns "+ret);
 *     return ret;
 *   }
 * }
 * </pre> */


public interface MethodInterceptor extends Interceptor {

    /**
     * Implement this method to perform extra treatments before and
     * after the invocation. Polite implementations would certainly
     * like to invoke {@link Joinpoint#proceed()}.
     *
     * @param invocation the method invocation joinpoint
     * @return the result of the call to {@link
     * Joinpoint#proceed()}, might be intercepted by the
     * interceptor.
     *
     * @throws Throwable if the interceptors or the
     * target-object throws an exception.  */
    Object invoke(MethodInvocation invocation) throws Throwable;
}



类前面的注释说明了该方法的使用,就是要在invoke()方法中调用MethodInvocation.proceed(),将执行传给下一个Interceptor,
最终执行目标方法。在proceed()方法前后加操作,到达Aroud advice的作用。




2,以下是使用 MethodInterceptor 接口实现的一个列子:



说明:
使用 BeanNameAutoProxyCreator 实现spring的自动代理
提到代理,我们可以使用ProxyBeanFactory,并配置proxyInterfaces,target和interceptorNames实现,
但如果需要代理的bean很多,无疑会对spring配置文件的编写带来繁重的工作.
Spring为我们提供了,根据beanName匹配后进行自动代理的解决方法.
(Spring拦截器,Spring方法拦截)
拦截器(也称拦截机)拦截机 (Interceptor), 是 AOP (Aspect-Oriented Programming) 的另一种叫法。


2.1,spring的配置如下:



<!-- spring方法拦截器类-->
<bean id="springMethodInterceptor" class="com.system.service.SpringMethodInterceptor">
<!-- <property name="param">
           <value>${param}</value>
        </property> -->
</bean>
<bean id="beanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames"> 
<list> 
                <value>*Service*</value>
                <value>*Dao*</value>
</list> 
</property> 
<property name="interceptorNames"> 
            <list> 
   <value>springMethodInterceptor</value> 
            </list>
</property> 
</bean>


2.2,SpringMethodInterceptor类如下:



package com.system.service;
import java.util.Date;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.struts2.ServletActionContext;
/**
 * @author Weijun Hu
 *
 */
public class SpringMethodInterceptor implements MethodInterceptor {
/**
private String param;
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
*/
public Object invoke(MethodInvocation mi) throws Throwable {
String interfaceName = mi.getMethod().getDeclaringClass().getName();
String className = mi.getThis().getClass().getName();
String methodName = mi.getMethod().getName();
System.out.println("调用的类为:" + className);
System.out.println("调用的方法为:" + methodName);
//以下几行是获取方法上的annotation
//MethodMark methodMark = mi.getMethod().getAnnotation(MethodMark.class);
//if(methodMark==null || !methodMark.isLog()){
// return mi.proceed();
//}
//Object[] args = mi.getArguments();
Object obj = null;
String errorInfo = "";
boolean pass = false;
try{
obj = mi.proceed();
pass = true;
}catch(Exception e){
e.printStackTrace();
errorInfo = e.getMessage();
throw e;
}finally{
if(obj!=null){
//TODO 
} 
//根据pass判断是否执行成功
}
return obj;
}
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值