问题:看了很多关于Spring AOP的文章,在讲各种切入方式(before、around、after-returnning、thrown等)时,被切入的业务主体Bean的方法,基本都是无参数的。
也有提到有参数的,但都是一个String型的参数。
以before为例,无参数方法的切点配置为
<aop:before method="before" pointcut="execution(* cn.xxxx..*.*(..))"/>
如果方法有一个String型的参数param,则配置为
<aop:before method="before" arg-names="param" pointcut="execution(* cn.xxxx..*.*(..)) and args(param)"/>
注:如果参数其实可为任何类型,即Object。如果非要强调是String型,参数为其他类型的方法,不想被切点切入,则可写成 method="before(java.lang.String)"
(经实际测试 arg-names="param" 不写也可以)
但如果 cn.xxxx..*.* 的方法有多个参数,且个数不定,要想让切点可以切入,这么个写法就不行了。
我搜了N多的帖子,也没能找到方法,最终几经辗转,终于在网友的帮助下,点破了这一层窗户纸,其实也很简单,还是在配置的写法:
<aop:before method="before" pointcut="execution(* cn.xxxx..*.*(..)) and args(..)"/>
与之配合的切点的写法是
public void before(JoinPoint jp) throws Throwable {
...
}
这样,不论业务Bean的方法有多少个参数,都可以被这个切点切入了。如果需要访问各个参数,只需
Object[] args = jp.getArgs();
----------------------------------华丽的分割线-----------------------------------
其实,能够满足如上需求的方法,至少还有一种,就是拦截器。
<bean id="myService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames">
<list>
<value>beforeInterceptor</value>
</list>
</property>
<property name="target">
<ref bean="realServiceTarget" />
</property>
</bean>
<bean id="realServiceTarget" class="cn.xxxx.xxx.Xxxx"/>
<bean id="beforeInterceptor" class="cn.xxxx.xxx.MyChecker"/>
思路是在注入ServiceBean时,偷梁换柱一下,用myService代替,实际是指向Spring的拦截器,它可以在执行真正的ServiceBean之前,先执行beforeInterceptor所指向的拦截代码
(这里是MyChecker,这个拦截器要实现org.aopalliance.intercept.MethodInterceptor接口,并完成public Object invoke(MethodInvocation invocation) throws Throwable方法)然后再交还给target属性指明的真正的ServiceBean。它不仅仅能够得到方法的参数,而且还有更强的功能——决定是否继续执行target。
public class MyChecker implements MethodInterceptor {
/**
* 用户访问认证方法。
* 如果登录合法则开始执行服务,否则返回错误。
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
Method invokeMethod = invocation.getMethod();
Object[] args = invocation.getArguments();
...
if(....){
return invocation.proceed(); // 检查OK,继续执行
}else{
return null; // 检查NG,阻断执行
}
}
}
看到了吧,这里不仅仅可以得到目标方法的参数 Object[] args = invocation.getArguments();
还可以,控制是否要继续执行目标方法,还是阻断。因此用来做认证是再合适不过了。
----------------------------------华丽的分割线-----------------------------------
为什么要加入两条分割线之间的之一段呢?除了也作为before切入的另一种实现方式,更主要的是想引出下面的问题:
我发现,在我成功的用AOP切入之后,每次都执行了两遍切点,且我检查了配置文件,并没有重复定义<AOP>
当我在切点代码中加入
Object target = jp.getTarget();
我发现,这个target有一次是我的ServiceBean,而另一次是类似$Proxy22之类的东西。这才恍然大悟,它应该是那个拦截器!也就是说,拦截器被切点切入了一次,真正的target又切入了一次。
显然,从配置文件的写法上似乎是无法避免拦截器被切入的(虽然org.springframework.aop.framework.* 并不是切面),那只能在切点里想办法回避了
public void before(JoinPoint jp) throws Throwable {
Object target = jp.getTarget();
if(AopUtils.isAopProxy(target)){
return;
}
...
}
至此,可以让多参数方法被切入的before切点完成了。
(after-returnning没有遇到什么障碍,多参数也很简单,甚至不用在pointcut配置中声明,还可取到返回值)
<aop:after-returning method="afterReturning" arg-names="retVal" returning="retVal" pointcut="execution(* cn.xxxx..*.*(..))"/>
切点,可以同时得到JoinPoint和返回值
public void afterReturning(JoinPoint jp, Object retVal) throws Throwable {
Object target = jp.getTarget();
if(AopUtils.isAopProxy(target)){
return;
}
...
}
最后,不知道哪位晓得,如果通过AOP而不是中间段落中提到的【拦截器】,来实现现有拦截器的功能,即取得入口参数,并可以控制继续执行被切的业务ServiceBean,还是阻止它执行。
如果能帮上我,请留言,谢谢了。
分享到:
相关推荐
2. **XML配置的AOP**:在传统的Spring配置中,我们需要在`<aop:config>`元素内定义切面、切入点和通知。虽然相比注解方式繁琐,但在某些情况下更具有灵活性。 压缩包中的`SpringAOPTest`可能包含了一个Spring AOP的...
这只是一个基础的例子,实际上,Spring AOP支持更复杂的场景,如方法参数匹配、注解匹配等,可以满足更多实际需求。在实际项目中,AOP不仅可以用于日志,还可以用于性能监控、事务管理、安全控制等多个方面,极大地...
在 Spring 框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者定义“切面”,这些切面可以封装跨多个对象的行为或责任。Spring AOP 提供了在运行时实现切面的功能,无需修改现有代码。本篇文章将详细...
总结,Spring AOP通过切面、切入点和通知等概念,提供了在不入侵原有代码的基础上,进行日志记录、事务管理、性能监控等多种跨切面操作的能力。在实际开发中,利用AOP可以有效地提高代码的复用性和模块化程度,降低...
【Spring AOP介绍1】 Spring AOP,全称为Spring面向切面编程,是Spring框架的重要组成部分,它提供了一种在不修改源代码的情况下,对现有代码进行增强的技术,以实现程序功能的统一控制。AOP的主要目的是降低业务...
2. **定义切面**:切面是AOP的核心,它包含通知(Advice)和切入点(Pointcut)。通知定义了在特定时机执行的行为,切入点则定义了何时应用这个通知。在XML配置中,你可以这样定义: ```xml <aop:config> <aop:...
在Spring AOP中,切面通常由一个或多个通知(advises)和一个切入点(join point)定义。 2. **通知(Advice)**:通知是在特定连接点执行的代码,如方法调用前、后或异常发生时。Spring支持五种类型的通知:前置...
1. **基于XML的配置**:通过在Spring配置文件中声明切面、切入点和通知来实现。 2. **基于注解的方式**:使用`@AspectJ`风格的注解来声明切面和通知。 #### 四、Spring AOP 的配置示例 下面是一个简单的基于注解的...
切入点的表达式通常通过切入点指示符来指定,例如,Spring AOP使用AspectJ的切入点表达式语法。 通知(Advice)是在连接点应用的行为,用以实现核心业务逻辑以外的功能。它包括前置通知(Before Advice)、后置通知...
- Spring AOP提供了更丰富的切面配置,如切入点表达式,可以精确控制切面应用的时机和位置。 5. **应用场景:** - 日志记录:在方法调用前后记录日志,无需在每个方法中手动插入日志代码。 - 性能监控:计算方法...
在Spring框架中,切入点(pointcut)表达式是AOP(面向切面编程)的核心组成部分,用于定义关注点的精确位置,比如哪些方法应该被拦截。切入点表达式是基于AspectJ语法的,允许开发者精确地指定要拦截的方法。下面将详细...
2. 配置切入点(Pointcut):切入点定义了何时应用通知。它可以是一个方法签名、注解或者一个复杂的表达式,确定哪些方法会受到通知的影响。 3. 通知的关联:将通知与切入点关联起来,指定在哪些方法执行前后(或...
1. **AspectJ的切入点表达式**:AspectJ的切入点表达式语言(Pointcut Expression Language, PEL)比Spring AOP的更强大,能够精确地定位到特定的类、方法甚至方法参数。 2. **AspectJ编译时织入**:AspectJ可以与...
在Spring AOP中,切面由通知(advice)和切入点(pointcut)定义。 2. **通知(Advice)**:通知是在特定连接点上执行的代码,即切面的行为。有五种类型的通知:前置通知(Before)、后置通知(After)、返回后通知...
在"struts2+spring aop demo"这个项目中,我们将探讨如何结合这两个框架,利用Spring的AOP功能来记录操作日志,特别是涉及自定义参数的AOP例子。 首先,让我们了解AOP的概念。面向切面编程(Aspect Oriented ...
通过这种方式,Spring AOP可以方便地帮助我们处理网关中的参数识别和处理问题,提高代码的复用性和可维护性。记住,AOP的核心在于解耦,让业务逻辑更专注于业务本身,而不是关注点的实现。在实际应用中,根据需求...
在Spring AOP中,切面可以由一个类定义,该类包含通知(advice)和切入点表达式(pointcut expression)。 2. **通知(Advice)**:通知是在特定连接点上执行的代码,它可以是前置通知(before advice)、后置通知...