1.Advice
分爲四種:
Before Advice,需要extends BeforeAdvice。重寫void before(Method m, Object[] args, Object target) throws Throwable;
After advice,需要extends Advice。重寫void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable;
注意After advice中可以訪問代理方法的返回值,但不能修改
環繞Advice
例子:
public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}
public class DebugInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before: invocation=[" + invocation + "]"); //(1)
Object rval = invocation.proceed();
System.out.println("Invocation returned"); //(2)
return rval;
}
}
invocation.proceed()方法運行指向連接點的攔截器鏈並返回proceed()的結果
Throws Advice
是一個空接口,起標識作用
實現方法afterThrowing([Method], [args], [target], Throwable)。
也可以爲afterThrowing( Throwable)
2.advisor
advisor會具有advice的功能並過濾所不需要代理的方法,只代理標識的方法
<!-- 配置advisor -->
<!-- 作用:篩選要攔截的方法 -->
<bean name="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!-- 注入advice -->
<property name="advice" ref="beforeAdvice"></property>
<!-- 注入需要被攔截的目標對象中的方法 -->
<property name="patterns">
<list>
<value>.*delete</value>
<value>.*update</value>
</list>
</property>
</bean>
3.AutoProxy
使用自動代理的時候需要注意的方面:
1.當前的配置裏面一定要有 一個advisor的配置
2.不需要向自動代理類中注入任何信息
3.不管目標對象是否實現了一個或多接口,自動代理的方式都能夠爲它產生代理對象.
4,如果目標對象是沒有實現接口的類,那麼將自動使用CGlib代理對象
5.從spring容器中拿代理對象的時候,需要通過目標對象的
名字來拿。
配置:
<bean name="proxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
</bean>
4.AutoProxyByName
使用自動代理byName的方式的時候需要注意的方面:
1.當前的配置裏有沒有advisor的配置都可以
2.需要向自動代理類中注入目標對象的名字和advisor或者advice
3.不管目標對象是否實現了一個或多接口,自動代理的方式都能夠爲它產生代理對象。
4,如果目標對象是沒有實現接口的類,那麼將自動使用CGlib代理對象
5.從spring容器中拿代理對象的時候,需要通過目標對象的名字來拿。
配置:
<!-- 這裏使用自動代理的方式 autoproxybyname -->
<bean name="proxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 注入需要被代理的對象名字 -->
<property name="beanNames">
<list>
<value>target2</value>
<value>target3</value>
</list>
</property>
<!-- 注入advice或者advisor -->
<property name="interceptorNames">
<list>
<value>beforeAdvice</value>
</list>
</property>
</bean>
6.aop:config標籤
需要更改約束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
例子:
<!-- 配置aop的代理 -->
<aop:config>
<!-- 定義一個切入點 並給切入點起名爲myPointCut -->
<!-- 切入點是一組連接點的集合 -->
<aop:pointcut expression="execution(public * com.ma.aop.before.MathImp.*(..))" id="myPointCut"/>
<!-- 定義哪一個advice在哪一個切入點上面起作用 -->
<aop:advisor advice-ref="beforeAdivce" pointcut-ref="myPointCut" />
</aop:config>
常見切入點表達式例子
1)任意公共方法的執行:
execution(public * *(..))
2)任何一個以“set”開始的方法的執行:
execution(* set*(..))
3)AccountService 接口的任意方法的執行:
execution(* com.briup.service.AccountService.*(..))
4)定義在service包裏的任意方法的執行:
execution(* com.briup.service..(..))
5)定義在service包或者子包裏的任意方法的執行:
execution(* com.briup.service...(..))
6)在service包裏的任意連接點(在Spring AOP中只是方法執行)
within(com.xyz.service.*)
7)在service包或者子包裏的任意連接點(在Spring AOP中只是方法執行) : within(com.xyz.service..*)