Spring AOP三種方式定義增強
阿新 • • 發佈:2019-02-17
一、通過實現(implements)的方式增強
BeforeLog:
package cn.log; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class BeforeLog implements MethodBeforeAdvice { /** * method 被呼叫的方法物件 * args 被呼叫的方法的引數 * target 被呼叫的方法的目標物件 * */ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("before---"+target.getClass().getName()+"的"+method.getName()+"方法被執行"); } }
AfterLog:
AroundLog:package cn.log; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; public class AfterLog implements AfterReturningAdvice { /** * 目標方法執行後的通知 * returnValue 返回值 * method 被呼叫的方法物件 * args 被呼叫的方法物件的引數 * target 被呼叫的方法物件的目標物件 * */ @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("after---"+target.getClass().getName()+"的"+method.getName()+"被成功執行,返回值是"+returnValue); } }
ErrorLog:package cn.log; import java.lang.reflect.Method; import java.util.Arrays; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class AroundLog implements MethodInterceptor { public Object invoke(MethodInvocation arg0) throws Throwable { Object target = arg0.getThis(); //獲取被代理的物件 Method method = arg0.getMethod(); //獲取被代理的方法 Object[] args = arg0.getArguments(); //獲取方法引數 System.out.println("環繞---呼叫" + target + "的 " + method.getName() + "方法。方法入參:"+ Arrays.toString(args)); try { Object result = arg0.proceed();//呼叫目標方法,獲取返回值 System.out.println("環繞---呼叫" + target + "的 " + method.getName() + "方法。" + "方法返回值:" + result); return result; } catch (Throwable e) { System.out.println(method.getName() + " 方法發生異常" + e); throw e; } } }
package cn.log;
import org.aspectj.apache.bcel.classfile.Method;
import org.springframework.aop.ThrowsAdvice;
/**
* 方法名必須是afterThrowing。方法的入參只有最後一個是必須的,前三個入參是可選的,但是前三個引數要麼都提供,要麼一個也不提供。正確的宣告方法舉例:
afterThrowing(Method method, Object[] args, Object target, SQLException ex)
afterThrowing(SQLException ex)
afterThrowing(RuntimeException ex)
錯誤的宣告方法舉例:
catchThrowing(RuntimeException ex):方法名錯誤
afterThrowing(Method method, RuntimeException ex):引數列表錯誤
* */
public class ErrorLog implements ThrowsAdvice{
public void afterThrowing(Method method, Object[] args, Object target,
RuntimeException e) {
System.out.println(method.getName() + " 方法發生異常:" + e);
}
}
---------UserService介面:
package cn.service;
public interface UserService {
public void add();
public String update(int i);
public void delete();
public void search();
}
UserServiceImpl:
package cn.service;
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("增加使用者");
}
@Override
public String update(int i) {
System.out.println("更新使用者");
return "success";
}
@Override
public void delete() {
System.out.println("刪除使用者");
}
@Override
public void search() {
System.out.println("查詢使用者");
}
}
beans.xml
<bean id="userService" class="cn.service.UserServiceImpl"/>
<bean id="beforeLog" class="cn.log.BeforeLog"/>
<bean id="afterLog" class="cn.log.AfterLog"/>
<bean id="errorLog" class="cn.log.ErrorLog"/>
<bean id="aroundLog" class="cn.log.AroundLog"/>
<aop:config>
<aop:pointcut expression="execution(* cn.service.UserServiceImpl.*(..))" id="pointcut"/>
<aop:advisor advice-ref="aroundLog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="errorLog" pointcut-ref="pointcut"/>
</aop:config>
--------------------
Test:package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.service.UserService;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
UserService userservice = (UserService)ac.getBean("userService");
//userservice.delete();
userservice.update(1);
}
}
輸出:
總結:
①:環繞增強在目標方法前後(環繞前、環繞後)都可以插入增強處理
②:環繞增強是spring中最強大的增強,Spring把目標方法的控制權全部給了它,可以獲取或者修改目標方法的引數和返回值,並且可以對方法進行異常處理和決定方法是否執行
注意一點:如果<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>放在
<aop:advisor advice-ref="aroundLog" pointcut-ref="pointcut"/>之前,執行的順序會變得不一樣
這僅僅是before和around的環繞前有這樣的效果,after始終都是在方法執行後執行,然後再到around的環繞後執行。
二、非註解的自定義類實現aop增強
Log:package cn.log;
/**
* 自定義類實現aop
* */
public class Log {
public void before()
{
System.out.println("方法執行前---55566-----");
}
public void after()
{
System.out.println("方法執行後--------");
}
}
beans.xml
<bean id="userService" class="cn.service.UserServiceImpl"/>
<bean id="log" class="cn.log.Log"/>
<aop:config>
<aop:aspect ref="log">
<aop:pointcut expression="execution(* cn.service.UserServiceImpl.*(..))" id="pointcut"/>
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
除了before、after之外,還可以自定義around、after-returning、after-throwing三、使用註解實現自定義aop增強
log:
package cn.log;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
/**
* 自定義類實現aop
* +++++++使用註解!!!
* */
@Aspect
public class Log {
@Before("execution(* cn.service.UserServiceImpl.*(..))")
public void before()
{
System.out.println("方法執行前--------");
}
@After("execution(* cn.service.UserServiceImpl.*(..))")
public void after()
{
System.out.println("方法執行後--------");
}
@Around("execution(* cn.service.UserServiceImpl.*(..))")
public void aroud(ProceedingJoinPoint jp) throws Throwable
{
System.out.println("環繞前");
System.out.println("簽名:"+jp.getSignature());
// Object result = jp.proceed();
jp.proceed();
System.out.println("環繞後");
// return result;
}
}
beans.xml<bean id="userService" class="cn.service.UserServiceImpl"/>
<bean id="log" class="cn.log.Log"/>
<aop:aspectj-autoproxy/>
Test:
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
UserService userservice = (UserService)ac.getBean("userService");
//userservice.add();
userservice.delete();
}
輸出:
三種方式定義增強使用建議:
Spring在定義切面時提供了多種選擇,應根據專案的具體情況做出選擇:
1、通過介面實現增強處理是較低版本Spring AOP的做法,如果在一個使用低版本Spring AOP開發的專案上進行升級,
可以考慮使用<aop:advisor>複用已經存在的增強類;
2、如果專案採用JDK 5.0或以上版本,可以考慮使用@AspectJ註解方式,減少配置的工作量;
3、如果不願意使用註解或專案採用的JDK版本較低無法使用註解,則可以選擇使用<aop:aspect>配合普通JavaBean的形式。