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个回答

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

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

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

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

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

可以通过arg-names

目标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 ===

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

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!