weid0907
2009-04-15 22:52
浏览 1.2k
已采纳

spring AOP中如何给通知传递参数

我想在不修改原对象代码的情况下,插入对域模型的数据搜集方法,需要传入1个参数。
例如:病人信息(PatientInfo)与病人信息操作日志(PatientInfoOperationLog),二者存在一对多的关系。
ORM映射配置中采用了级联,病人信息操作日志为被动插入操作。
在CreatePatientAction中采集病人信息的数据,并对病人信息执行显式的save。
这样看来,病人信息操作日志的信息与Action并没有什么关联,可以视为独立运作单元;而且,如果以后不打算采用这个日志的时候,可以修改配置直接修改或删除AOP和ORM映射配置就可以了。
前段时间考虑过spring是否可以注入方法,经过讨论发现是不可行的。这样我打算使用AOP,但我尝试了AOP配置,在没有传递参数的情况下,可以正常执行通知。但我需要配置2个对象之间的关系,不得不传入病人信息作为参数来完成任务,但不知道怎么配置这个参数。

我尝试过加入arg-names属性,但服务器启动时就报错,没加这个属性也会报错,因为通知调用的方法是有参数的。

而且还有个疑问,这个参数是否可以是一个已经实例化的引用?我需要的是这个引用,而不能是新创建的对象,因为这没有意义。

我的配置如下,这里是没有加arg-names属性:
aop:config



/aop:aspect
/aop:config

PatientInfoOpeLogPlugin类代码如下:

public void plugin(PatientInfo patientInfo){

log.setOperation(defaultOperation);
log.setOperateTime(this.now());
log.setOperator("admin");
log.setPatientInfo(patientInfo);
Set logSet= new HashSet ();
logSet.add(log);
patientInfo.setOperationLog(logSet);

}

服务器启动错误概要信息如下:
有没有配置arg-names的情况都一样:
…… Constructor threw exception; nested exception is java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut
……

[b]问题补充:[/b]
请一楼给个例子我试试,谢谢!
[b]问题补充:[/b]
[size=small][color=blue]三楼whistler的例子是标准例子。看后我考虑了一下,如果对Service类的相关方法进行拦截,确实可以达到我想要的结果,而且还可以不受Struts2的自带拦截器影响。其实,我原来的想法集中在如何让AOP拦截Action了,但后来经过查询资料和测试,发现无法达到,因为Struts2本身也对Action做了处理,与AOP的拦截发生了冲突。如果不拦截Action,就没有这个问题了。
谢谢你、谢谢大家的回复![/color][/size]

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

5条回答 默认 最新

  • iteye_19131 2009-04-24 17:16
    已采纳

    public void plugin(PatientInfo patientInfo);作为一个前置通知执行,你可以绑定连接点(spring只能是方法)的参数。

    而作为连接点的patient.base.action.CreatePatientAction.execute(..)方法的参数应该是HttpServletRequest request, HttpServletResponse response等,并没有PatientInfo类型的参数,所以你是不可能从连接点的执行获得PatientInfo类型的对象。

    我想你的连接点应该是包含PatientInfo类型的参数的业务层类吧,而不是action的方法,
    楼上绑定参数的方法应该都是对的

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • wanghaolovezlq 2009-04-16 09:32

    arg-names是显式地指定参数名称,你的就是arg-names="patientInfo"

    这个的写法就不对匹配到有参数的plugin方法了

    评论
    解决 无用
    打赏 举报
  • weixin_42297497 2009-04-24 15:02

    可以通过arg-names

    评论
    解决 无用
    打赏 举报
  • iteye_19131 2009-04-24 18:01

    目标bean,showValues(String value)方法执行作为连接点
    [code="java"]public class InitializingBeanNameClass
    public String showValues(String [color=red]value[/color])
    {
    System.out.println("目标方法执行:");
    System.out.println("传入参数:String arg: " + value);
    return value;
    }
    }[/code]

    切面,bindMethodArgTest(String argvalue)方法作为通知
    [code="java"]public class BindArgs {
    public void bindMethodArgTest(String [color=red]argvalue[/color]) {
    System.out.println("BindMethodArgTest通知,通过args(argvalue,..)绑定showValues(java.lang.String,..)第一个参数......");
    System.out.println("参数:" + argvalue);
    }
    }[/code]

    [code="java"] xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    aop:aspectj-autoproxy/

    aop:config


    /aop:aspect
    /aop:config



    [/code]

    public static void main(String[] args) {

    ApplicationContext context = new ClassPathXmlApplicationContext("com/spring/ch4/pointcut/xml/pointcut-tests.xml");
    
    InitializingBeanNameClass nameBean = (InitializingBeanNameClass) context.getBean("nameBean");
    
    System.out.println("=== GOING TO testBeforeAdvice ===");
    
    nameBean.showValues("方法参数绑定");
    
    System.out.println("=== FINISHED  testBeforeAdvice ===");
    

    }

    执行结果

    === GOING TO testBeforeAdvice ===
    BindMethodArgTest通知,通过args(argvalue,..)绑定showValues(java.lang.String,..)第一个参数......
    参数:方法参数绑定

    目标方法执行:
    传入参数:String arg: 方法参数绑定
    === FINISHED testBeforeAdvice ===

    评论
    解决 无用
    打赏 举报
  • iteye_19131 2009-04-24 18:04

    不好意思,argvalue我想置为红色,结果没管用,也不能改了

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题