最近在系统中须要实现用户某些操做添加积分, 但愿实现对系统现有的代码进行最小嵌入,所以使用Spring AOP的切面编程将很好实现该需求,达到最小耦合度。在Spring AOP中的通知都是针对方法层级进行通知,相对与Struct中针对类层级通知,具备更好的灵活性。
html
/*方法拦截*/ MethodInterceptor /*返回拦截*/ AfterReturningAdvice /*事件拦截*/ HandlerInterceptor MethodInvocation
一、经典的基于代理的AOP(各版本Spring)
java
二、@AspectJ注解驱动的切面(仅Spring 2.0);
正则表达式
三、纯POJO切面(仅Spring2.0);
spring
四、注入式AspectJ切面(各版本Spring)express
一、before advice 在方法执行前执行。
二、after returning advice 在方法执行后返回一个结果后执行
三、after throwing advice 在方法执行过程当中抛出异常后执行
四、around advuce 综合执行以上三种状况编程
一、建立通知:实现通知的这几个接口,并实现其中的方法app
a)org.springframework.aop.MethodBeforeAdvice框架
b)org.springframework.aop.AfterReturningAdviceide
c)org.springframework.aop.ThrowsAdviceui
d)org.aopalliance.intercept.MethodInterceptor
e)org.springframework.aop.IntroductionInterceptor
二、定义切点和通知者:在Spring配制文件中配置这些信息
三、使用ProxyFactoryBean来生成代理
要想实现Spring AOP 仅仅针对某一指定的方法进行切面编程,而不是针对全部的方法进行切面编程,那么须要指定切入点(pointcut) ,pointcut经过制定方法名进行拦截方法,同时pointcut必须advisor进行关联。pointcut能够经过指定彻底方法名或经过正则表达式进行匹配方法。
<bean id="namePointCut" class="org.springframework.aop.support.NameMatchMethodPointcut"> <property name="mappedName" value="insertTestStudent" /> </bean>
org.springframework.aop.support.NameMatchMethodPointcut:表示该切点经过直接经过彻底方法名匹配方法的,property中的value就是完整的方法名。
<bean id="addGuideIntegralAfterTesting" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value=".*insertTestStudent"/> </bean>
结合通知者advisor
<bean id="audienceAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="audienceAdvice" /> <property name="pointcut" ref="performancePointcut" /> </bean>
org.springframework.aop.support.DefaultPointcutAdvisor是个通知者类,他只是把通知关联给切入点
联合切入点是比较特殊的正则表达式切入点,他同时结合了切入点和通知者
<bean id="addGuideIntegralAfterTesting" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice" ref="guideIntegralAfterAdvice" /> <property name="patterns"> <list> <value>.*insertTestStudent</value> </list> </property> </bean>
从AspectJ里定义切点的方式就能够看出AspectJ的切点语言是一种真正的切点表达语言。 类org.springframework.aop.aspectj.AspectJExpressionPointcut被用来定义AspectJ切点表达式
<bean id="performancePointcut" class="org.springframework.aop.aspectj.AspectJExpressionPointcut"> <property name="expression" value="execution(* Performer+.perform(..))" /> </bean>
经过使用DefaultPointcutAdvisor把切入点和通知者结合起来。咱们能够利用特殊的通知者,把切点表达式定义为通知者的一个属性。对于AspectJ表达式来讲,使用的通知者类是org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor:
<bean id="audienceAdvisor" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor"> <property name="advice" ref="audienceAdvice" /> <property name="expression" value="execution(* Performer+.perform(..))" /> </bean>
通知者把通知与切点关联起来,从而完整地定义一个切面。
切面在Spring里是以代理方式实现的,因此仍然须要代理目标Bean才能让通知者发挥做用,如下有两种方式显示代理,一经过ProxyFactoryBean方式或者经过自动代理。
<!--定义个联合代理--> <bean id="addIntegralAutoProxyAop" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <!--须要监听的接口--> <value>guideStudentService</value> </list> </property> <property name="interceptorNames"> <list> <!-- 与第一个bean的id相匹配 --> <value>addGuideIntegralAfterTesting</value> </list> </property> </bean>
Spring的ProxyFactoryBean是个工厂Bean,用于生成一个代理,把一个或多个通知者应用到Bean
<bean id="duke" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="dukeTarget" /> <property name="interceptorNames"> <list> <value>audienceAdvisor</value> </list> </property> </bean>
<!--定义个联合代理--> <bean id="addIntegralAutoProxyAop" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <!--须要监听的接口--> <value>guideStudentService</value> </list> </property> <property name="interceptorNames"> <list> <!-- 与第一个bean的id相匹配 --> <value>addGuideIntegralAfterTesting</value> </list> </property> </bean>
<!-- 定义通知advice --> <bean id="guideIntegralAfterAdvice" class="com.rrtong.interceptors.GuideIntegralAfterAdvice" /> <!-- 定义pointcut和通知者advisor的联合切入点和通知者 --> <bean id="addGuideIntegralAfterTesting" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <!-- 引用通知接口的实现类 --> <property name="advice" ref="guideIntegralAfterAdvice" /> <!-- 正则表达式匹切入点方法名 --> <property name="patterns"> <list> <value>.*insertTestStudent</value> </list> </property> </bean> <!-- 定义自动代理 --> <bean id="addIntegralAutoProxyAop" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>guideStudentService</value> </list> </property> <property name="interceptorNames"> <list> <value>addGuideIntegralAfterTesting</value> </list> </property> </bean>
joinpoint就是程序执行过程当中可以插入到切面的一个点,这个点就是方法被调用时,异常抛出时,甚至字段被编辑时。切面代码经过这个点插入到程序的通常流程中,从而添加新的行为。
pointcut做用就是缩小切面通知范围
http://blog.csdn.net/sin90lzc/article/details/7486145
http://blog.163.com/zzf_fly/blog/static/209589158201382314454298/
http://blog.csdn.net/topwqp/article/details/8695180