- 一個普通的類 -> 通知類
a.實現接口 b.註解
-a.實現接口
將一個普通類設置爲通知類
通知類 (實現的接口)分爲前置通知(MethodBeforeAdvice),後置通知(AfterReturningAdvice),環繞通知(MethodInvoction),異常通知(ThrowsAdvice),最終通知(AfterAdvice)。
我只做其中的一個,剩下的幾乎就是照葫蘆畫瓢
下面的代碼是我寫的一個後置通知的實現類,實現的接口是org.springframework.aop.AfterReturningAdvice
public class LogAfter implements AfterReturningAdvice{
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("後置通知:目標對象"+target+",調用的方法名:"
+method.getName()+",方法參數"+Arrays.toString(args)+",返回值"+returnValue);
}
}
接下來我們需要在applicationContext.xml中配置切點和切面。
切點就是我們實現類,切面是我們需要是在某個方法後面實現實現類。
<!-- 配置事務管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 增加對事務的支持 -->
<tx:annotation-driven
transaction-manager="txManager" />
<bean id="studentDao" class="edu.ahau.dao.impl.StudentDaoImpl">
</bean>
<!-- 通知所在的類,也就是繼承接口的類位置 被稱爲aop的切面-->
<bean id="logAfter" class="edu.ahau.aop.LogAfter">
</bean>
<!--配置後置通知 -->
<aop:config>
<!--設置的是切點 也就是需要添加通知類的方法-->
<aop:pointcut expression="execution(public * edu.ahau.service.impl.StudentServiceImpl.addStudent(..))" id="pointCut"/>
<!--左邊的是切面 右邊是切點-->
<aop:advisor advice-ref="logAfter" pointcut-ref="poiontCut"/>
</aop:config>
————————————————————————————————————————————
-
b.註解
註解其實跟上面的實現接口是差不多的,但是我們不用實現接口,直接在類裏面定義方法
- 直接給出AOP中類的代碼
@Component("logAnnotation")//<bean id="logAnnotation" class="edu.ahau.aop.LogBeforeAnnotation">
@Aspect //此類是一個通知
public class LogBeforeAnnotation {
@Before("execution(public * edu.ahau.service.impl.StudentServiceImpl.addStudent(..))")
public void myBefore(JoinPoint jp) {
System.out.println("【註解形式,顯示前置通知】:目標對象"+jp.getTarget()+",方法名:"+jp.getSignature().getName()+",參數列表:"+Arrays.toString(jp.getArgs()));
}
@AfterReturning(pointcut = "execution(public * edu.ahau.service.impl.StudentServiceImpl.addStudent(..))", returning = "returningValue")
public void myAfter(JoinPoint jp,Object returningValue) {
System.out.println("【註解形式,顯示前置通知】:目標對象"+jp.getTarget()+",方法名:"+jp.getSignature().getName()+",參數列表:"+Arrays.toString(jp.getArgs())+"返回值:");
System.out.println("【註解形式,顯示後置通知】");
}
/* 只會捕捉指定的異常 */
@Around("execution(public * edu.ahau.service.impl.StudentServiceImpl.addStudent(..))")
public void myAround(ProceedingJoinPoint pjpp) {
System.out.println("<環繞通知-前置對象>。。。。。");
try {
pjpp.proceed();
System.out.println("<環繞通知-後置對象>。。。。");
} catch (Throwable e) {
}
}
@AfterThrowing(pointcut = "execution(public * edu.ahau.service.impl.StudentServiceImpl.addStudent(..))",throwing = "e")
public void myThrow(JoinPoint jp,NullPointerException e) {
System.out.println("<註解形式--異常通知>"+e.getMessage());
}
@After("execution(public * edu.ahau.service.impl.StudentServiceImpl.addStudent(..))")
public void myAfter() {
System.out.println("<<<<<<<<<<<<<<<<<<<最終通知>>>>>>>>>>>>>>>>>>>>>>>>");
}
}
從上面的代碼我們可以看到我們將通過將實現接口的方法轉換成註解的形式
下面是對類裏面的註解進行簡單的解釋
- @Before
- 括號裏面的就相當於我們在實現類
<aop:pointcut expression="execution(public * edu.ahau.service.impl.StudentServiceImpl.addStudent(..))" id="pointCut"/>
對切點的信息進行獲取需要用到JoinPoint。
- @AfterAfterReturning
- 如果我們需要返回值,則需要在類方法括號添加Object類型的returningValue,並且在註解裏面設置
returning = "returningValue"
類方法的參數名和註解裏面的名字是一樣的。
剩餘的都和前面兩個類似。
注意的是:我們在一個類裏寫了環繞通知和異常通知,我們需要注意,環繞通知裏面的獲取異常可能會覆蓋住異常通知,環繞通知裏面的拋出異常類不是Exception,而是Throwable ,導致異常通知沒有顯示。
然後就是在applicationContext中配置
<context:component-scan base-package="edu.ahau.aop"></context:component-scan>
<aop:aspectj-autoproxy ></aop:aspectj-autoproxy>
這<aop:aspectj-autoproxy ></aop:aspectj-autoproxy>
是開啓註解形式的通知