1、pointCut定义
<bean id="pointCutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>act*</value>
</list>
</property>
</bean>
2、before advice
自定义的before advice需要实现MethodBeforeAdvice
接口:
public class TestBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] objects, Object o) throws Throwable
{
System.out.println("TestBeforeAdvice | method is " + method.getName() +
" object is "+o.getClass().getName());
}
}
3、throws advice
自定义的throws advice需要实现ThrowsAdvice
接口,并在接口中定义afterThrowing方法。
afterThrowing方法有4种重载方式。
public class TestThrowAdvice implements ThrowsAdvice
{
public void afterThrowing(Exception e)
{
System.out.println("TestThrowAdvice| afterThrowing 1");
}
public void afterThrowing(RemoteException e)
{
System.out.println("TestThrowAdvice| afterThrowing 2");
}
public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
{
System.out.println("TestThrowAdvice| afterThrowing 3"+
"method is "+method.getName()+
"target is "+target.getClass().getName() );
}
public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)
{
System.out.println("TestThrowAdvice| afterThrowing 4"+
"method is "+method.getName()+
"target is "+target.getClass().getName() );
}
}
4、after returning advice
自定义的返回后通知需要实现AfterReturningAdvice
接口,定义afterReturning
方法。方法中可以访问返回值,但是不能进行修改。如果抛出异常,则会抛出拦截器链,替代返回值
public class TestAfterReturningAdvice implements AfterReturningAdvice {
public void afterReturning(Object o, Method method,
Object[] objects, Object o1)
{
System.out.println("TestAfterReturningAdvice| method is "+
method.getName());
}
}
5、环绕通知Interception
自定义的环绕通知,需要实现MethodInterceptor
接口,实现invoke
方法。
public class TestMethodInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable
{
System.out.println("TestMethodInterceptor| invoke 1,"+
methodInvocation.getMethod().getName()+","+
methodInvocation.getStaticPart().getClass().getName());
Object o = methodInvocation.proceed();
System.out.println("TestMethodInterceptor| invoke 2,"+
methodInvocation.getMethod().getName()+","+
methodInvocation.getStaticPart().getClass().getName());
return o;
}
}
6、ProxyFactoryBean
ProxyFactoryBean用于生成对应的代理类,配合上述通知,共同实现API方式的AOP功能。
注入:
<bean id="pointCutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>act*</value>
</list>
</property>
</bean>
<bean id="testBeforeAdvice" class="learn.advice.TestBeforeAdvice"/>
<bean id="afterReturningAdvice" class="learn.advice.TestAfterReturningAdvice"/>
<bean id="testThrowAdvice" class="learn.advice.TestThrowAdvice"/>
<bean id="testMethodInterceptor" class="learn.advice.TestMethodInterceptor"/>
<bean class="learn.service.ControllerImlp" id="controllerImlpTarget"/>
<bean id="defaultPointcutAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="testBeforeAdvice"/>
<property name="pointcut" ref="pointCutBean"/>
</bean>
<bean id="controllerImlp" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="learn.interfaces.IController"/>
<property name="target" ref="controllerImlpTarget"/>
<property name="interceptorNames">
<list>
<value>defaultPointcutAdvisor</value>
<value>afterReturningAdvice</value>
<value>testThrowAdvice</value>
<value>testMethodInterceptor</value>
</list>
</property>
</bean>
执行:
IController helloService = (IController) context.getBean("controllerImlp");
helloService.action();
结果
TestBeforeAdvice | method is action object is learn.service.ControllerImlp
TestMethodInterceptor| invoke 1,action,java.lang.reflect.Method
action!!!!!
TestMethodInterceptor| invoke 2,action,java.lang.reflect.Method
TestAfterReturningAdvice| method is action
说明:
-
程序代码中,可以看到只有before advice是通过切入点进行匹配的,其他通知未进行接入点匹配。从运行结果可以看到,默认是能够执行所有对应通知的。pointCut的意义在于进行更精确的匹配。
-
在ProxyFactoryBean中如果指定了proxyInterfaces,则一定会走JDK的代理。如果对应的对象没有接口,则会使用CGLIB代理。
- 可以使用内部匿名bean来隐藏目标和代理之间的差别。
<bean id="controllerImlp" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="learn.interfaces.IController"/>
<!--这里直接定义bean,不再使用ref-->
<property name="target">
<bean class="learn.service.ControllerImlp"/>
</property>
<property name="interceptorNames">
<list>
<value>defaultPointcutAdvisor</value>
<value>afterReturningAdvice</value>
<value>testThrowAdvice</value>
<value>testMethodInterceptor</value>
</list>
</property>
</bean>
-
如果在
interceptorNames
属性中使用通配符"*"
匹配通知,则只能匹配Interceptor
,其他通知无法匹配 - 使用父子bean简化xml定义
<!--定义父bean-->
<bean id="baseProxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"
abstract="true"/>
<!--使用父bean-->
<bean id="controllerImlp" parent="baseProxyFactoryBean">
<property name="proxyInterfaces" value="learn.interfaces.IController"/>
<property name="target" ref="controllerImlpTarget"/>
<property name="interceptorNames">
<list>
<value>defaultPointcutAdvisor</value>
<value>afterReturningAdvice</value>
<value>testThrowAdvice</value>
<value>testMethodInterceptor</value>
</list>
</property>
</bean>
- 使用Spring AOP可以不依赖于IoC,也可以通过硬编码实现,只是不推荐。
使用BeanNameAutoProxyCreator
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="con*"/>
<property name="interceptorNames">
<list>
<value>testBeforeAdvice</value>
</list>
</property>
</bean>
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦