`
TonyLian
  • 浏览: 402078 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring AOP 前切入点及多参数问题

阅读更多
问题:看了很多关于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,还是阻止它执行。

如果能帮上我,请留言,谢谢了。
3
0
分享到:
评论
6 楼 mwgdmc 2014-02-11  
解决问题了。多谢!
5 楼 waterwindsxu 2013-11-05  
好文章,转载了
4 楼 chj738871937 2013-05-17  
有用,问题解决了。
3 楼 jinnianshilongnian 2012-11-20  
引用
即取得入口参数,并可以控制继续执行被切的业务ServiceBean,还是阻止它执行。
我觉得这个还是用环绕通知吧。
2 楼 TonyLian 2012-11-20  
ghyghost 写道
不知道练习AOP有啥用,除了用spring写底层的东西

在不干扰主业务的前提下,插入辅助处理。

比如,在一个已经部署好的ATM提款机上,新装个摄像头。你一插卡(before)就拍一张照片,

你退卡走人(after)时再拍一张。

为了这个摄像头,动ATM的主程序显然是不合适的,且它已经在运行中了,谁也不敢轻易动。


在实际使用中,比如之前的身份认证、之后的写日志、对参数、返回值的数据加工。。。等

都是应用场景
1 楼 ghyghost 2012-11-20  
不知道练习AOP有啥用,除了用spring写底层的东西

相关推荐

    JavaEE Spring AOP使用

    2. **XML配置的AOP**:在传统的Spring配置中,我们需要在`&lt;aop:config&gt;`元素内定义切面、切入点和通知。虽然相比注解方式繁琐,但在某些情况下更具有灵活性。 压缩包中的`SpringAOPTest`可能包含了一个Spring AOP的...

    spring AOP入门实例

    这只是一个基础的例子,实际上,Spring AOP支持更复杂的场景,如方法参数匹配、注解匹配等,可以满足更多实际需求。在实际项目中,AOP不仅可以用于日志,还可以用于性能监控、事务管理、安全控制等多个方面,极大地...

    Spring AOP依赖jar包

    在 Spring 框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者定义“切面”,这些切面可以封装跨多个对象的行为或责任。Spring AOP 提供了在运行时实现切面的功能,无需修改现有代码。本篇文章将详细...

    Spring AOP的简单实现

    总结,Spring AOP通过切面、切入点和通知等概念,提供了在不入侵原有代码的基础上,进行日志记录、事务管理、性能监控等多种跨切面操作的能力。在实际开发中,利用AOP可以有效地提高代码的复用性和模块化程度,降低...

    SpringAOP介绍1

    【Spring AOP介绍1】 Spring AOP,全称为Spring面向切面编程,是Spring框架的重要组成部分,它提供了一种在不修改源代码的情况下,对现有代码进行增强的技术,以实现程序功能的统一控制。AOP的主要目的是降低业务...

    spring AOP myeclipse 完整代码

    2. **定义切面**:切面是AOP的核心,它包含通知(Advice)和切入点(Pointcut)。通知定义了在特定时机执行的行为,切入点则定义了何时应用这个通知。在XML配置中,你可以这样定义: ```xml &lt;aop:config&gt; &lt;aop:...

    Spring AOP 项目

    在Spring AOP中,切面通常由一个或多个通知(advises)和一个切入点(join point)定义。 2. **通知(Advice)**:通知是在特定连接点执行的代码,如方法调用前、后或异常发生时。Spring支持五种类型的通知:前置...

    spring Aop文档

    1. **基于XML的配置**:通过在Spring配置文件中声明切面、切入点和通知来实现。 2. **基于注解的方式**:使用`@AspectJ`风格的注解来声明切面和通知。 #### 四、Spring AOP 的配置示例 下面是一个简单的基于注解的...

    Spring5_AOP.pdf

    切入点的表达式通常通过切入点指示符来指定,例如,Spring AOP使用AspectJ的切入点表达式语法。 通知(Advice)是在连接点应用的行为,用以实现核心业务逻辑以外的功能。它包括前置通知(Before Advice)、后置通知...

    Spring AOP精讲

    例如,事务管理的通知可以应用于一组跨越多个对象的方法上,这就是通过切入点实现的。 **5. 引入(Introduction)** 引入是指向被通知的类添加新方法或字段的过程。Spring允许引入新的接口到任何被通知的对象。...

    通过动态代理模拟Spring AOP

    - Spring AOP提供了更丰富的切面配置,如切入点表达式,可以精确控制切面应用的时机和位置。 5. **应用场景:** - 日志记录:在方法调用前后记录日志,无需在每个方法中手动插入日志代码。 - 性能监控:计算方法...

    详解Spring 框架中切入点 pointcut 表达式的常用写法

    在Spring框架中,切入点(pointcut)表达式是AOP(面向切面编程)的核心组成部分,用于定义关注点的精确位置,比如哪些方法应该被拦截。切入点表达式是基于AspectJ语法的,允许开发者精确地指定要拦截的方法。下面将详细...

    JDK动态代理 spring aop 的原理

    2. 配置切入点(Pointcut):切入点定义了何时应用通知。它可以是一个方法签名、注解或者一个复杂的表达式,确定哪些方法会受到通知的影响。 3. 通知的关联:将通知与切入点关联起来,指定在哪些方法执行前后(或...

    SpringAOP+AspectJ

    1. **AspectJ的切入点表达式**:AspectJ的切入点表达式语言(Pointcut Expression Language, PEL)比Spring AOP的更强大,能够精确地定位到特定的类、方法甚至方法参数。 2. **AspectJ编译时织入**:AspectJ可以与...

    spring AOP 例子参考

    在Spring AOP中,切面由通知(advice)和切入点(pointcut)定义。 2. **通知(Advice)**:通知是在特定连接点上执行的代码,即切面的行为。有五种类型的通知:前置通知(Before)、后置通知(After)、返回后通知...

    struts2+spring aop demo

    在"struts2+spring aop demo"这个项目中,我们将探讨如何结合这两个框架,利用Spring的AOP功能来记录操作日志,特别是涉及自定义参数的AOP例子。 首先,让我们了解AOP的概念。面向切面编程(Aspect Oriented ...

    spring Aop 自动识别参数,比较实用,可以织入到网关转发的功能模块中

    通过这种方式,Spring AOP可以方便地帮助我们处理网关中的参数识别和处理问题,提高代码的复用性和可维护性。记住,AOP的核心在于解耦,让业务逻辑更专注于业务本身,而不是关注点的实现。在实际应用中,根据需求...

    最简单的SpringAOP入门案例

    在Spring AOP中,切面可以由一个类定义,该类包含通知(advice)和切入点表达式(pointcut expression)。 2. **通知(Advice)**:通知是在特定连接点上执行的代码,它可以是前置通知(before advice)、后置通知...

Global site tag (gtag.js) - Google Analytics