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..*)