咱们使用Spring的AOP功能的时候发现,咱们使用普通的配置方式的时候,咱们没法精确的肯定将切面类中的哪一个方法切入到哪一个切入点上,spring
因此咱们可使用aop的专用标签来完成相关的配置.其中主要表现是使用AspectJ的expression的操做express
aop:config标签
使用aop的专用标签来完成相关的配置.其中主要表现是使用AspectJ的expression的操做:
修改模式 类型 说明式 名称模式(参数模式)
execution(modifiers-pattern ret-type-pattern declaring-type-pattern name-pattern(param-pattern)
抛出模式
throws-pattern)除了返回类型模式,名字模式和参数模式之外,全部的部分都是可选的。
返回类型模式决定了方法的返回类型必须依次匹配一个链接点。
你会使用的最频繁的返回类型模式是 *,它表明了匹配任意的返回类型。
一个全称限定的类型名将只会匹配返回给定类型的方法。
名字模式匹配的是方法名。 你可使用 * 通配符做为全部或者部分命名模式。
参数模式稍微有点复杂:() 匹配了一个不接受任何参数的方法, 而 (..) 匹配了一个接受任意数量参数的方法(零或者更多)。
模式 (*) 匹配了一个接受一个任何类型的参数的方法。
模式 (*,String) 匹配了一个接受两个参数的方法,第一个能够是任意类型,第二个则必须是String类型
注意在使用以前须要在xml文件的beans标签中加入新的schame文件:并在Eclipse中进行关联配置spa
<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">
下面给出一些常见切入点表达式的例子。
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..*.*(..))
execution(* com.briup.service..*.*(..)) or execution(* com.briup.dao..*.*(..))代理
注意:
1.从spring容器中拿代理对象的时候也是要用目标对象的名字来拿。
2.没有实现任何接口的目标对象也能产生代理对象。
<!-- 配置aop的代理 -->
<!--注意:<aop:config proxy-target-class="true"> 若是这样配置则是强制使用CGLIB方式进行代理-->
<aop:config>
<!-- 定义一个切入点 并给切入点起名为myPointCut -->
<!-- 切入点是一组链接点的集合 -->
<aop:pointcut expression="execution(public * com.briup.aop.service.*.*(..))" id="myPointCut"/>
<!-- 定义哪个advice在哪个切入点上面起做用 -->
<aop:advisor advice-ref="beforeAdvice" pointcut-ref="myPointCut" />
</aop:config>
<!--
expression="execution(public * com.briup.aop.service.*.*(..))"
这个引号""里面就是用表达式的方式来定义切入点,只要是符合咱们这个表达式要求的
方法就是咱们的链接点,链接点的集合就是咱们要定义的切入点。
表达式中从左到右的*号:
第一个* 表示方法的返回类型不限。
第二个* 表示包中的任意一个类
第三个* 表示类中的任意一个方法
同时方法的参数也没有限制.
-->code
在一个切面类中定个多个方法,根据xml文件的配置每一个方法均可以织入到切入点的不一样位置,而且advice是在aop的标签中进行配置,不须要再写对应的advice类了xml
例如:
这个类至关于咱们以前的切面类
只不过这个切面类中有不少方法均可以织入到切入点上面
咱们能够控制把这里的任何一个方法织入到任何一个切入点上面对象
public class XmlHandler { public void beforeTest(JoinPoint p){ System.out.println(p.getSignature().getName()+" before..."); } public void afterTest(JoinPoint p){ System.out.println(p.getSignature().getName()+" after..."); } public void afterReturningTest(JoinPoint p){ System.out.println(p.getSignature().getName()+" afterReturning"); } //在和aroundAdvice结合的时候,这个方法必定要加上这个ProceedingJoinPoint类型的参数 public Object aroundTest(ProceedingJoinPoint pjp)throws Throwable{ //JoinPoint对象不能调用链接点所表示的方法 //ProceedingJoinPoint能调用链接点所表示的方法 pjp.proceed() System.out.println(pjp.getSignature().getName()+" is start.."); //调用到链接点方法 Object obj = pjp.proceed(); System.out.println(pjp.getSignature().getName()+" is end.."); return obj; } public void throwingTest(JoinPoint p,Exception ex){ System.out.println(p.getSignature().getName()+" is throwing..."+ex.getMessage()); } }
xml文件配置:blog
<!-- 配置dao层对象 --> <bean id="dao" class="com.briup.aop.dao.AccountDaoImpl"/> <!-- 配置目标对象 --> <bean name="target" class="com.briup.aop.service.AccountServiceImpl"> <property name="accountDao" ref="dao"></property> </bean> <!-- 配置切面类 --> <bean name="handler" class="com.briup.aop.xml.XmlHandler"></bean> <!-- 配置aop的代理 --> <aop:config> <!-- 定义切入点名为myPointCut --> <aop:pointcut expression="execution(public * com.briup.aop.service.*.*(..))" id="myPointCut"/>
<!-- 定义切面类 以及须要使用的advice --> <aop:aspect id="aspect" ref="handler"> <!-- 表示beforeAdvice会把切面类handler中的beforeTest方法织入到名字叫myPointCut的切入点上面 --> <aop:before method="beforeTest" pointcut-ref="myPointCut"/> <!-- after表示无论方法是否正常结束都会起做用 --> <aop:after method="afterTest" pointcut-ref="myPointCut"/> <!-- after-returning表示方法正常结束才会起做用(抛异常时候不起做用) --> <aop:after-returning method="afterReturningTest" pointcut-ref="myPointCut"/> <aop:around method="aroundTest" pointcut-ref="myPointCut"/> <!-- throwing="ex"表示throwingTest方法中接收异常对象的名字必定要是ex --> <aop:after-throwing method="throwingTest" pointcut-ref="myPointCut" throwing="ex"/> </aop:aspect> </aop:config>
注意:<aop:config proxy-target-class="true"> 若是这样配置则是强制使用CGLIB方式进行代理接口