坑向: 关于在IDEA中 以XML形式 实现Spring AOP编程时,在xml配置文件中给 连接点的前置通知before 传递参数时出现Unbound pointcut parameter错误的排查

坑向: 关于在IDEA中 以XML形式 实现Spring AOP编程时,在xml配置文件中给 连接点的前置通知before 传递参数时出现Unbound pointcut parameter错误的排查

    • 1. 环境介绍
        • 1.1 开发环境
        • 1.2 spring-config.xml的 beans标签的 相关命名空间属性
    • 2.1 错误介绍
    • 2.2 原目的 及 错误相关的 代码环境 介绍
        • 2.2.1 原目的
        • 2.2.2 错误相关的 代码环境
    • 3.1 错误排查(发现编写的代码正确)
    • 3.2 带着错误执行程序
    • 4. 编译环境提示错误的原因分析 和 解决方案
        • 4.1 原因分析
        • 4.2 Unbound pointcut parameter错误解决方案

1. 环境介绍

1.1 开发环境

IntelliJ IDEA 2018.3 x64

1.2 spring-config.xml的 beans标签的 相关命名空间属性

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd ">
<!-- 此处省略 -->
</beans>

2.1 错误介绍

在为 连接点 ProceedingJoinPoint 以XML形式 添加 可以传递参数的 before方法时,编译环境提示异常:Unbound pointcut parameter ‘user2’
坑向: 关于在IDEA中 以XML形式 实现Spring AOP编程时,在xml配置文件中给 连接点的前置通知before 传递参数时出现Unbound pointcut parameter错误的排查_第1张图片

2.2 原目的 及 错误相关的 代码环境 介绍

2.2.1 原目的

实现基于XML形式的Spring AOP编程,为连接点的添加 带有参数的 前置通知 before

具体思路为: 为一个Bean 创建 输出其信息的接口,然后实现该接口,最终设计一个切面类对该实现的接口方法进行一定的拦截和管理,使其前置通知可以传递被拦截的连接点方法的参数。

2.2.2 错误相关的 代码环境

① 使用的Bean类 User2.java

package com.castle.beans;

import java.io.Serializable;

public class User2 implements Serializable {
     
    private Long id;
    private String userName;
    private String note;

    public Long getId() {
     
        return id;
    }

    public void setId(Long id) {
     
        this.id = id;
    }

    public String getUserName() {
     
        return userName;
    }

    public void setUserName(String userName) {
     
        this.userName = userName;
    }

    public String getNote() {
     
        return note;
    }

    public void setNote(String note) {
     
        this.note = note;
    }

    @Override
    public String toString() {
     
        return id + " " + userName + ": " + note;
    }
}

② 设计的接口和相应实现类 User2XMLService.java 与 User2XMLServiceImp.java

package com.castle.service;

import com.castle.beans.User2;

public interface User2XMLService {
     
    void printUser2(User2 user2);
}

//=================================================================

package com.castle.service;

import com.castle.beans.User2;

public class User2XMLServiceImp implements User2XMLService {
     
    @Override
    public void printUser2(User2 user2) {
     
        System.err.println(user2);
    }
}

③ 设计的切面类 User2XMLAspect.java

package com.castle.aspect;

import com.castle.beans.User2;
import org.aspectj.lang.ProceedingJoinPoint;

import static com.castle.tools.PrintTool.*;

public class User2XMLAspect {
     
    public void before(User2 user2){
     
        println("XML before... [" + user2.getUserName() + "]");
    }

    public void around(ProceedingJoinPoint joinPoint){
     
        println("XML around before...");
        try{
     
            joinPoint.proceed();
        }catch (Throwable e){
     
            e.printStackTrace();
        }
        println("XML around after...");
    }

    public void after(){
     
        println("XML after...");
    }

    public void afterThrowing(){
     
        println("XML after throwing...");
    }

    public void afterReturning(){
     
        println("XML after returning...");
    }
}

④ 最终的spring-config2.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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd ">

    <bean id="user2" class="com.castle.beans.User2">
        <property name="id" value="99"/>
        <property name="userName" value="Rugal"/>
        <property name="note" value="I am the king of fighters"/>
    </bean>

    <bean id="service1" class="com.castle.service.User2XMLServiceImp"/>

    <bean id="aspect1" class="com.castle.aspect.User2XMLAspect"/>

    <aop:config>
        <aop:aspect ref="aspect1">
            <aop:pointcut id="printUser2" expression=
                    "execution(* com.castle.service.User2XMLServiceImp.printUser2(..))"/>
            <aop:before method="before" pointcut=
                    "execution(* com.castle.service.User2XMLServiceImp.printUser2(..)) and args(user2)"/>
            <aop:around method="around" pointcut-ref="printUser2"/>
            <aop:after method="after" pointcut-ref="printUser2"/>
            <aop:after-returning method="afterReturning" pointcut-ref="printUser2"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="printUser2"/>
        </aop:aspect>
    </aop:config>

</beans>

⑤ 测试代码

    /**
     * 测试使用纯XML方法,无注解实现Spring的AOP编程,对连接点方法进行拦截管理
     */
    public static void test17(){
     
        ApplicationContext xmlContext = new ClassPathXmlApplicationContext("spring-config2.xml");
        User2XMLService service = (User2XMLService) xmlContext.getBean("service1");
        User2 user2 = (User2) xmlContext.getBean("user2");
        service.printUser2(user2);
    }

3.1 错误排查(发现编写的代码正确)

仔细检查
在切面类中关于给before方法传递的参数 为 user2

public void before(User2 user2){
     
        println("XML before... [" + user2.getUserName() + "]");
    }

在xml配置文件中指定切点的表达式中 要求获取的参数 也为 user2没有发现名称不一致

<aop:before method="before" pointcut=
                    "execution(* com.castle.service.User2XMLServiceImp.printUser2(..)) and args(user2)"/>

3.2 带着错误执行程序

结果成功运行,并且 切点拦截的连接点方法 被成功执行了 所设计的前置通知before(), 其参数user2的userName也被 成功传递!

public void before(User2 user2){
     
        println("XML before... [" + user2.getUserName() + "]");
    }

userName 被成功提取出来为 Rugal 【此时依然存在Unbound pointcut parameter错误】

坑向: 关于在IDEA中 以XML形式 实现Spring AOP编程时,在xml配置文件中给 连接点的前置通知before 传递参数时出现Unbound pointcut parameter错误的排查_第2张图片

4. 编译环境提示错误的原因分析 和 解决方案

4.1 原因分析

也许关于切点的表达式书写正确,并无错误,是编译器或者xml配置文件参照的xsd文件存在一些bug。
即:

<aop:before method="before" pointcut=
                    "execution(* com.castle.service.User2XMLServiceImp.printUser2(..)) and args(user2)"/>

此语句本无编译错误,IDEA出现误报

4.2 Unbound pointcut parameter错误解决方案

① 修改 IDEA编译的 检查配置, 取消AOP子标签下的 Advice parameters检查

坑向: 关于在IDEA中 以XML形式 实现Spring AOP编程时,在xml配置文件中给 连接点的前置通知before 传递参数时出现Unbound pointcut parameter错误的排查_第3张图片

② 压制参数名称检查 ArgNamesErrorsInspection

即添加代码

			<!--suppress ArgNamesErrorsInspection -->
            <aop:before method="before" pointcut=
                    "execution(* com.castle.service.User2XMLServiceImp.printUser2(..)) and args(user2)"/>

最终没有了Error的红色下划线提示(变成警告也行):
坑向: 关于在IDEA中 以XML形式 实现Spring AOP编程时,在xml配置文件中给 连接点的前置通知before 传递参数时出现Unbound pointcut parameter错误的排查_第4张图片

你可能感兴趣的:(SSM,java,spring,aop,xml,intellij,idea)