关于Schema-based AOP support 遇到的问题解决

本文探讨了在Spring框架中使用AspectJ进行面向切面编程(AOP)时遇到的问题及解决方案,特别是关于如何正确使用args属性匹配方法参数。
在以aspectj方式声明AOP的时候,spring官方的参考手册中的对args的用法一直都是这样
   <!-- this is the object that will be proxied by Spring's AOP infrastructure -->
   <bean id="fooService" class="x.y.service.DefaultFooService"/>
   <!-- this is the actual advice itself -->
   <bean id="profiler" class="x.y.SimpleProfiler"/>
   <aop:config>
      <aop:aspect ref="profiler">
         <aop:pointcut id="theExecutionOfSomeFooServiceMethod"
                    expression="execution(* x.y.service.FooService.getFoo(String,int))
                    and args(name, age)"/>
         <aop:around pointcut-ref="theExecutionOfSomeFooServiceMethod"
                  method="profile"/>
      </aop:aspect>
   </aop:config>
注意name,age都是getFoo方法的临时变量名,而我在开发的时候按照这样的写法却报错warning no match for this type name: XX。在我把name,age换成String, int这两种类型名称后,很意外却能正常工作,
我开发的代码如下:
<aop:pointcut id="prefixPointCut"
         expression="execution(* services.OcsServices.add*(..)) and args(prefix)" />
<aop:after pointcut-ref="prefixPointCut" method="afterAdd" arg-names="prefix" />
其中prefix是我另外定义的bean:
  <bean id="prefix" class="pojo.Prefix">
  </bean>
Advice触发的LogAop类的方法定义如下:
    public void afterAdd(Prefix p) {
        System.out.println(p.getMvnoname() +"  afterAdd execute......");
}
被Aop的类OcsServices的方法定义为:
public void add(Object o){
   …….
}
上面这些相关定义能正常的工作。但是当我将prefix改成o后(因为官方的定义都是定义为o,是临时变量名),即报异常warning no match for this type name: o;这个问题困扰了我3天,google了无数,论坛发帖求解,都无济于事,最后发现还是得靠自己。最后终于以官方教程得方式设置成功了,怎么做得呢?
<aop:pointcut id="prefixPointCut"
         expression="execution(* services.OcsServices.add(Object)) and args(o)" />
<aop:after pointcut-ref="prefixPointCut" method="afterAdd" arg-names="o" />
Advice触发的LogAop类的方法定义如下:
    public void afterAdd(Object o) {
        Prefix p = (Prefix)o;
        System.out.println(p.getMvnoname() +"  afterAdd execute......");
}
被Aop的类OcsServices的方法定义为:
public void add(Object o){
   …….
}
可以发现,所有得相关得参数都一致改成了o,很有意思,原来问题就在于我们必须对保持变量名一致,尽管这个变量运行在不同得方法不同得类中。
对于我们配置aop:after-returning这样可以捕获返回值得aop,目前也遇到了类似得问题,只是猜想类似而已,看配置:
      <aop:pointcut id="prefixPointCutQuery"
         expression="execution(* services.OcsServices.query(Object, int, int)) and args(Object, int, int)" />
      <aop:after-returning
         pointcut-ref="prefixPointCutQuery"
         returning="retVal"
         method="afterAddReturn"/>
Advice触发的LogAop类的方法定义如下:
    public void afterAddReturn(Object retVal){
        System.out.println(retVal);
}
被Aop的类OcsServices的方法定义为:
public List query(Object o, int page, int perpage){
    ………
}
上面这样得关联配置可以正常工作,但是当我改成这样后:
      <aop:pointcut id="prefixPointCutQuery"
         expression="execution(* services.OcsServices.query(Object, int, int)) and args(o, page, perpage)" />
同样报错warning no match for this type name: o;
但是当我改成:
      <aop:pointcut id="prefixPointCutQuery"
         expression="execution(* services.OcsServices.query(..))" />
却又是成功的。难道aop中的advice触发的方法没有使用o, page, perpage的话在args定义就会出现问题?这个原因没有能够得到官方的说法。
### 关于AOP编程的代码示例 #### 使用Spring AOP基于Schema的方式实现日志记录功能 为了展示如何通过Spring AOP来增强应用程序的功能而不修改现有代码,在此提供一个简单的例子,该实例展示了如何利用XML配置文件定义切面逻辑并将其应用于目标对象的方法调用上。 首先,在`pom.xml`中添加必要的依赖项以便支持Spring框架以及AOP模块[^1]: ```xml <dependencies> <!-- Spring Core & Context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring AOP support --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <!-- AspectJ Weaver (if using @Aspect annotations or pointcut expressions) --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency> </dependencies> ``` 接着创建一个名为`logging-aspect.xml`的Spring配置文件用于声明切入点表达式和相应的建议(advice),这里采用的是schema-based风格的配置[^2]: ```xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 定义切面bean --> <bean id="loggerAdvice" class="com.example.LoggingAdvice"/> <!-- 配置aop命名空间下的advisor元素指定应用哪个advice到哪些连接点 --> <aop:config> <aop:pointcut expression="execution(* com..service.*.*(..))" id="businessService"/> <aop:before method="logBefore" pointcut-ref="businessService" /> </aop:config> </beans> ``` 最后编写具体的拦截器类`LoggingAdvice.java`,它实现了MethodBeforeAdvice接口从而允许在方法执行前插入自定义行为: ```java package com.example; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class LoggingAdvice implements MethodBeforeAdvice { public void before(Method m, Object[] args, Object target) throws Throwable { System.out.println("Executing:" + m.getName() + ", arguments = " + Arrays.toString(args)); } } ``` 上述代码片段演示了怎样借助Spring AOP的基础架构特性轻松地向现有的服务层组件注入额外的日志记录能力而无需更改原有业务逻辑。这种方式不仅提高了系统的可维护性和灵活性,同时也遵循了面向方面编程的核心理念——即关注分离原则.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值