spring <aop:pointcut>标签 expression属性如何定义路径

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring <aop:pointcut>标签 expression属性如何定义路径相关的知识,希望对你有一定的参考价值。

假如要设置com.aptech.jb.epet.dao.hibimpl包里类的方法请问expression属性如何设置

任意公共方法的执行:
execution(public * *(..))
任何一个名字以“set”开始的方法的执行:
execution(* set*(..))
AccountService接口定义的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))
在service包中定义的任意方法的执行:
execution(* com.xyz.service.*.*(..))
在service包或其子包中定义的任意方法的执行:
execution(* com.xyz.service..*.*(..))
在service包中的任意连接点(在Spring AOP中只是方法执行):
within(com.xyz.service.*)
在service包或其子包中的任意连接点(在Spring AOP中只是方法执行):
within(com.xyz.service..*)
在service包或其子包中的任意连接点(在Spring AOP中只是方法执行):within(com.xyz.service..*)
实现了AccountService接口的代理对象的任意连接点 (在Spring AOP中只是方法执行):
this(com.xyz.service.AccountService)
'this'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得代理对象在通知体内可用。实现AccountService接口的目标对象的任意连接点 (在Spring AOP中只是方法执行):
target(com.xyz.service.AccountService)
'target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得目标对象在通知体内可用。任何一个只接受一个参数,并且运行时所传入的参数是Serializable 接口的连接点(在Spring AOP中只是方法执行)
args(java.io.Serializable)
'args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得方法参数在通知体内可用。请注意在例子中给出的切入点不同于
execution(* *(java.io.Serializable)):
args版本只有在动态运行时候传入参数是Serializable时才匹配,而execution版本在方法签名中声明只有一个 Serializable类型的参数时候匹配。目标对象中有一个 @Transactional 注解的任意连接点 (在Spring AOP中只是方法执行)
@target(org.springframework.transaction.annotation.Transactional)
'@target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。任何一个目标对象声明的类型有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行):
@within(org.springframework.transaction.annotation.Transactional)
'@within'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。任何一个执行的方法有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行)
@annotation(org.springframework.transaction.annotation.Transactional)
'@annotation'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。任何一个只接受一个参数,并且运行时所传入的参数类型具有@Classified 注解的连接点(在Spring AOP中只是方法执行)
@args(com.xyz.security.Classified)
'@args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。任何一个在名为'tradeService'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
bean(tradeService)
任何一个在名字匹配通配符表达式'*Service'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
bean(*Service)
参考技术A execution(* com.aptech.jb.epet.dao.hibimpl.*.*(..))
这样写应该就可以了
这是com.aptech.jb.epet.dao.hibimpl 包下所有的类的所有方法。。
第一个*代表所有的返回值类型
第二个*代表所有的类
第三个*代表类所有方法
最后一个..代表所有的参数。
参考技术B 楼上的是正解。
execution(* com.aptech.jb.epet.dao.hibimpl.*.*(..))
参考技术C 有比官方提供的api描述的更清楚的么?还带例子

Spring 在XML中声明切面/AOP

在Spring的AOP配置命名空间中,我们能够找到声明式切面选择。看以下:

	<aop:config>					<!-- AOP定义開始 -->
		<aop:pointcut/>				<!-- 定义切入点 -->
		<aop:advisor/>				<!-- 定义AOP通知器 -->
		<aop:aspect>				<!-- 定义切面開始 -->
			<aop:pointcut/>			<!-- 定义切入点 -->
			<aop:before/>			<!-- 前置通知 -->
			<aop:after-returning/>	        <!-- 后置返回通知 -->
			<aop:after-throwing/>           <!-- 后置异常通知 -->
			<aop:after/>			<!-- 后置通知(无论通知的方法是否运行成功) -->
			<aop:around/>			<!-- 围绕通知 -->
			<aop:declare-parents/>          <!-- 引入通知  -->
		</aop:aspect>				<!-- 定义切面结束 -->
	</aop:config>					<!-- AOP定义结束 -->

一、声明切面

切面就是包括切入点和通知的对象,在Spring容器中将被定义为一个Bean。Schema方式的切面须要一个切面支持Bean,该支持Bean的字段和方法提供了切面的状态和行为信息,并通过配置方式来指定切入点和通知实现。

 

    切面使用<aop:aspect>标签指定,ref属性用来引用切面支持Bean。

 

    切面支持Bean“aspectSupportBean”跟普通Bean全然一样使用。切面使用“ref”属性引用它。

二、  声明切入点

    切入点在Spring中也是一个Bean。Bean定义方式能够有非常三种方式:

    1)在<aop:config>标签下使用<aop:pointcut>声明一个切入点Bean,该切入点能够被多个切面使用。对于须要共享使用的切入点最好使用该方式,该切入点使用id属性指定Bean名字。在通知定义时使用pointcut-ref属性通过该id引用切入点。expression属性指定切入点表达式:


<aop:config>
	<aop:pointcut expression="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))" id="pointcut"/>
	<aop:aspect ref="audienceAspect" >
		<aop:before pointcut-ref="pointcut" method="taskSeats"/>
	</aop:aspect>
</aop:config>
 2)在<aop:aspect>标签下使用<aop:pointcut>声明一个切入点Bean,该切入点能够被多个切面使用,但一般该切入点仅仅被该切面使用,当然也能够被其它切面使用,但最好不要那样使用,该切入点使用id属性指定Bean名字,在通知定义时使用pointcut-ref属性通过该id引用切入点。expression属性指定切入点表达式:
	<aop:config>
		<aop:aspect ref="audienceAspect" >
			<aop:pointcut expression="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))" id="pointcut"/>
			<aop:before pointcut-ref="pointcut" method="taskSeats"/>
		</aop:aspect>
	</aop:config>

    3)匿名切入点Bean。能够在声明通知时通过pointcut属性指定切入点表达式,该切入点是匿名切入点,仅仅被该通知使用:
	<aop:config>
		<aop:aspect ref="audienceAspect" >
			<aop:before pointcut="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))" method="taskSeats"/>
		</aop:aspect>
	</aop:config>

三、   声明通知

直接来看个样例:
package cn.com.ztz.spring.service;

public interface ShowService {
	public void show();
}
package cn.com.ztz.spring.service;

public class ShowServiceImpl implements ShowService{
	@Override
	public void show() {  
	    showBefore();
		//showError();//异常測试
	    showEnd();
	}
	public void showBefore(){
		System.out.println("showBefore============");
	}
	public void showError(){
		System.out.println("showError============");
		throw new RuntimeException();
	}
	public void showEnd(){
		System.out.println("showEnd===============");
	}
}

package cn.com.ztz.spring.service;
public class AudienceAspect {
	public void taskSeats(){
		System.out.println("等候节目開始===");
	}
	public void applaud(){
		System.out.println("鼓掌=========");
	}
	public void demandRefund(){
		System.out.println("退钱离场======");
	}
}
   <bean id="showService" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
    <bean id="audienceAspect" class="cn.com.ztz.spring.service.AudienceAspect"/>
	<aop:config>
		<aop:pointcut id="pointcut" expression="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))"/>
		<aop:aspect ref="audienceAspect" >
			<aop:before pointcut-ref="pointcut" method="taskSeats"/>
			<aop:after-returning pointcut-ref="pointcut" method="applaud"/>
			<aop:after-throwing pointcut-ref="pointcut" method="demandRefund"/>
		</aop:aspect>
	</aop:config>
public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");  
	    ShowService hs = ctx.getBean("showService", ShowService.class);  
	    System.out.println("======================================");
	    hs.show();
	    System.out.println("======================================");
	}
控制台输出结果:
======================================
等候节目開始===
showBefore============
showEnd===============
鼓掌=========
======================================

四、 为通知传递參数

如今有非常多人在观看演出,我想传入一个人姓名,怎么办了。来看下:
public interface ShowService {
	public void showBefore(String param);
}
public class ShowServiceImpl implements ShowService{
	public void showBefore(String param){
		System.out.println("showBefore============");
	}
}
<pre name="code" class="java">public class AudienceAspect {
	public void taskSeats(String param){
		System.out.println(param+",等候节目開始===");
	}
}

   <bean id="showService" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
    <bean id="audienceAspect" class="cn.com.ztz.spring.service.AudienceAspect"/>
	<aop:config>
		<aop:aspect ref="audienceAspect" >
			<aop:before pointcut="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..)) and args(param)" 
						method="taskSeats(java.lang.String)"
						arg-names="param"/>
		</aop:aspect>
	</aop:config>

public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");  
	    ShowService hs = ctx.getBean("showService", ShowService.class);  
	    System.out.println("======================================");
	    hs.showBefore("张三");
	    System.out.println("======================================");
	}
控制台输出结果:
======================================
张三,等候节目開始===
showBefore============
======================================

五、  声明围绕通知

围绕着在切入点选择的连接点处的方法所运行的通知。围绕通知很强大,能够决定目标方法是否运行,什么时候运行,运行时是否须要替换方法參数,运行完成是否须要替换返回值,可通过<aop:aspect>标签下的<aop:around >标签声明:
围绕通知第一个參数必须是org.aspectj.lang.ProceedingJoinPoint类型,在通知实现方法内部使用ProceedingJoinPoint的proceed()方法使目标方法运行。proceed 方法能够传入可选的Object[]数组,该数组的值将被作为目标方法运行时的參数。
public interface ShowService {
	public void showAround(String param);
}
public class ShowServiceImpl implements ShowService{
	public void showAround(String param){
		System.out.println("showAround============"+param);
	}
}
public class AudienceAspect {
	public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {  
	    System.out.println("around before advice===========");  
	    Object retVal = pjp.proceed(new Object[] {"around"});  
	    System.out.println("around after advice===========");  
	    return retVal; 
	}
}
   	<bean id="showService" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
    <bean id="audienceAspect" class="cn.com.ztz.spring.service.AudienceAspect"/>
	<aop:config>
		<aop:aspect ref="audienceAspect" >
			<aop:around pointcut="execution(* cn.com.ztz.spring.service.ShowServiceImpl.*(..))" 
						method="aroundAdvice"/>
		</aop:aspect>
	</aop:config>
public static void main(String[] args) {
	<span style="white-space:pre">	</span>ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");  
	    ShowService hs = ctx.getBean("showService", ShowService.class);  
	    System.out.println("======================================");
	    hs.showAround("张三");
	    System.out.println("======================================");
	}
控制台输出结果:
======================================
around before advice===========
showAround============around
around after advice===========
======================================

六、引入

一些编程语言。比如Ruby和Groovy。有开放类的理念。

它们可以不用直接改动对象或类的定义可以为对象或类添加新的方法。不幸的是。java不是动态的语言,一旦编译完毕了。我们非常难再为该类加入新的功能了。

自己想想我们如今不是一直在用切面吗?实际上,利用被称为引入的AOP概念。切面能够为spring bean加入新的方法。

 Spring引入同意为目标对象引入新的接口,通过在< aop:aspect>标签内使用< aop:declare-parents>标签进行引入。


<aop:declare-parents  
          types-matching="AspectJ语法类型表达式"  
          implement-interface=引入的接口"               
          default-impl="引入接口的默认实现"  
          delegate-ref="引入接口的默认实现Bean引用"/>

看下样例:我们定义了个新的接口和实现
public interface DeclareService {
	public void declare();
}

public class DeclareServiceImpl implements DeclareService {
	@Override
	public void declare() {
		System.out.println("declare=====================");
	}
}

   	<bean id="showService" class="cn.com.ztz.spring.service.ShowServiceImpl"/>
    <bean id="declareService" class="cn.com.ztz.spring.service.DeclareServiceImpl"/>
	<aop:config>
		<aop:aspect>
			<aop:declare-parents types-matching="cn.com.ztz.spring.service.ShowServiceImpl+"
								 implement-interface="cn.com.ztz.spring.service.DeclareService"
								 delegate-ref="declareService"/>
		</aop:aspect>
	</aop:config>

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");  
		DeclareService hs = ctx.getBean("showService", DeclareService.class);  
	    System.out.println("======================================");
	    hs.declare();
	    System.out.println("======================================");
	}

我们获得还是showService的Bean,执行下測试方法输出结果:
======================================
declare=====================
======================================



























以上是关于spring <aop:pointcut>标签 expression属性如何定义路径的主要内容,如果未能解决你的问题,请参考以下文章

spring aop pointcut 表达式求助

Spring 在XML中声明切面/AOP

spring11----基于Schema的AOP

22_AOP_切面

阿里的Spring框架面试题到底有多难?

6.AOP配置与应用(xml的方式)