1.AOP的切入點
連接點(Joint Point)指的是程序運行的某個階段點,如某個方法的調用、異常拋出等。切入點(Pointcut)是連接點位置的集合,指明觸發通知(Advice)的條件。Advice是某個連接點處的處理邏輯,也就是注入到連接點的代碼。
2.Spring AOP切入點的3種實現
2.1 靜態切入
靜態切入點只限於給定的方法和目標類,而不考慮方法的參數。Spring在調用靜態切入點時只在第一次調用的時候計算靜態切入點的位置,然後緩存起來。通過org.springframework.aop.support.RegexpMethodPointcut可以實現靜態切入點,是一個通用的正則表達式切入點。
<bean id="setPointcut" class="org.springframework.aop.support.RegexpMethodPointcut">
<property name="patterns">
<!--設定切入點-->
<list>
<value>.*save.*</value>
<value>.*do.*</value>
</list>
</property>
</bean>
.*save.*表示所有以save開頭的方法都是切入點
2.2 動態切入點
動態切入點不僅限於給點的方法和類,動態切入點還可以指定方法的參數。因爲參數具有變化性,所以動態切入點不能緩存。因此使用動態切入點對性能具有很大的損耗。
當切入點在執行時需要根據執行參數來調用Advice的時候,就需要使用動態切入點。Spring提供了內建的動態切入點:控制流切入點。此切入點匹配當前線程的調用堆棧。開發人員只有在當前線程執行時找到特定的類和特定的方法才能返回true。
大多數情況下都是使用靜態切入點。
2.3 自定義切入點
因爲Spring的切入點時JAVA類,所以可以自定義切入點。
3.Spring AOP的通知(Advice)
Spring提供了5中Advice類型:Interception Around、Before、After Returning、Thrown和Introductio。觸發調用的情景爲:在JointPoint前後、JointPoint前、JointPoint後、JointPoint拋出異常時、JointPoint調用完畢後。
3.1 Before通知
Before通知只在JointPoint前執行,實現Before通知的類需要實現接口MethodBeforeAdvice
public class XxxBeforeAdvice implements MethosBeforeAdvice {
public void before(Method m,Object[] args,Object target) throws Throwable{
//切入點處理邏輯
}
}
3.2 After Returning通知
Before通知只在JointPoint前執行,實現Before通知的類需要實現接口MethodAfterAdvice
public class XxxBeforeAdvice implements MethosAfterAdvice {
public void after(Method m,Object[] args,Object target) throws Throwable{
//切入點處理邏輯
}
}
3.3 Throw通知
Throw通知只在JointPoint拋出異常時執行,實現Throw通知的類需要實現接口ThrowAdvice
public class XxxBeforeAdvice implements ThrowAdvice{
public void afterThrowing(Method m,Object[] args,Object target) throws Throwable{
//切入點處理邏輯
}
}
3.4 Introduction通知
Introduction通知只在JointPoint調用完畢後執行,實現Introduction通知的類需要實現接口IntroductionAdvisor和接口IntroductionInterceptor
4.Spring的Advisor
Advisor是Pointcut和Advice的配置器,它是將Advice注入到程序中的Pointcut的代碼。在Spring中主要通過XML配置的方式來配置Pointcut和Advice。
<bean id="exceptionHandlerAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice">
<ref bean="exceptionHandler"/>
</property>
<!-- 指定對任何方法都有效 -->
<property name="patterns">
<value>.*.*</value>
</property>
</bean>
5. Spring AOP的代理
5.1 Java自動代理
使用Java自動代理是,添加以下配置
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
然後配置上相應的Advisor即可。
5.2 CGLIB代理
5.2.1面向接口編程
添加如下配置,標記需要代理的接口、接口的實現類(target)和對應的Advisor。new對象時通過下面的此bean的id即可實現CGLIB代理
<bean id="logic1proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.test.aop.service.LogicInterface</value>
</property>
<property name="target">
<ref bean="logic1"/>
</property>
<property name="interceptorNames">
<list>
<value>timeHandlerAdvisor</value>
</list>
</property>
</bean>
5.2.2 面向類編程
添加如下配置,target中爲需要代理的類,並配置上相應的Advisor即可。
<bean id="logic2proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="target">
<ref bean="logic2"/>
</property>
<property name="interceptorNames">
<list>
<value>exceptionHandlerAdvisor</value>
</list>
</property>
</bean>