• 8 -- 深入使用Spring -- 4...6 AOP代理:基于注解的XML配置文件的管理方式


          8.4.6 基于XML配置文件的管理方式

            Spring 2.x 提供一个新的aop:命名空间来定义切面、切入点和增强处理。

            XML配置方式优点:

              ⊙ 如果应用没有使用JDK 1.5 以上版本,那么应用只能使用XML配置方式来管理切面、切入点和增强处理等。

              ⊙ 采用XML配置方式时对早期的Spring用户来说更加习惯,而且这种方式允许使用纯粹的POJO来支持AOP。当使用AOP作为工具来配置企业服务时,XML会是一个很好的选择。

            当使用XML风格时,可以在配置文件中清晰地看出系统中存在那些切面。

            XML配置费方式缺点:

              ⊙ 使用XML配置方式不能将切面、切入点、增强处理等封装到一个地方。如果需要查看切面、切入点、增强处理,必须同时结合Java文件和XML配置文件来查看;但使用@AspectJ时,则只需要一个单独的类文件即可看到切面、切入点和增强处理的全部信息。

              ⊙ XML配置方式比@AspectJ方式有更多的限制:仅支持“singleton”切面Bean,不能在XML中组合多个命名连接点的声明。

            @AspectJ切面还有一个优点,就是能被Spring AOP和AspectJ同时支持,如果有一天需要将应用改为使用AspectJ来实现AOP,使用@AspectJ将非常容易迁移到基于AspectJ的AOP实现中。

            在Spring 配置文件中,所有的切面、切入点和增强处理都必须定义在<aop:config.../>元素内部。

            <beans.../>元素下可以包含多个<aop:config.../>元素,一个<aop:config>可以包含pointcut、advisor和aspect元素,且这三个元素必须按照此顺序来定义。

            <aop:config.../>元素所包含的子元素如图:

              图图图图图图图图图图图图图图图图图图

              图                图

              图                图

              图                图

              图                图

              图                图

              图                图

              图图图图图图图图图图图图图图图图图图

            注意:

              使用<aop:config.../>方式进行配置时,可能与Spring的自动代理方式相冲突,例如使用<aop:aspectj-autoproxy/>或类似方式显式启用了自动代理,则可能会导致出现问题(比如有些增强处理没有被织入)。因此建议:要么全部使用<aop:config.../>配置方式,要么全部使用自动代理方式,不要两者混合使用。

            1.配置切面

              定义切面使用<aop:aspect.../>元素,使用该元素来定义切面时,其实质是将一个已有的Spring Bean转换成切面Bean,所以需要先定义个一个普通的Spring Bean。

              因为切面Bean可以当成一个普通的Spring Bean来配置,所以完全可以为该切面Bean 配置依赖注入。当切面Bean定义完成后,通过在<aop:aspect.../>元素中使用ref属性来引用该Bean,就可以该Bean转换成一个切面Bean了。

              配置<aop:aspect.../>元素时可以指定如下三个属性:

                ⊙ id : 定义该切面的标识名。

                ⊙ ref : 用于该ref属性所引用的普通Bean转换为切面Bean。

                ⊙ order : 指定该切面Bean的优先级,该属性的作用与前面@AspectJ中的@Order注解、Ordered接口的作用完全一样,order属性值越小,该切面对应的优先级越高。

              扩展:关于Order接口点这里,暂时懒得看。留在明天的明天的明天的明天的明天有空再看吧。

              配置定义一个切面:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:P="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <!-- 定义一个普通Bean实例,该Bean实例将作为Aspect Bean -->
        <bean id="afterAdviceBean" class="edu.pri.lime._8_4_6.xmlaspect.AfterAdviceTest" />
    
        <aop:config>
            <!-- 将容器中AfterAdviceBean转换成切面Bean 切面Bean的新名称为:afterAdviceAspect -->
            <aop:aspect id="afterAdviceAspect" ref="afterAdviceBean"
                order="100"/>
        </aop:config>
    
    
    </beans>

              由于Spring支持将切面Bean当成普通Bean来管理,所以完全可以利用依赖注入来管理切面Bean,管理切面Bean的属性值、依赖管理等。

            2.配置增强处理

              使用XML一样可以配置Before、After、AfterReturning、AfterThrowing、Around五种增强处理,而且完全支持和@AspectJ完全一样的语义。

              使用XML配置增强处理分别依赖于如下几个元素:

                ⊙ <aop:before.../> : 配置Before增强处理。

                ⊙ <aop:after.../> : 配置After增强处理。

                ⊙ <aop:after-returning.../>:配置AfterReturning增强处理。

                ⊙ <aop:after-throwing.../>:配置AfterThrowing增强处理。

                ⊙ <aop:around.../> : 配置AfterThrowing增强处理。

              这些元素都不支持使用子元素,但通常可指定如下属性:

                ⊙ pointcut : 该属性指定一个切入表达式,Spring将在匹配该表达式的连接点时织入该增强处理。

                ⊙ pointcut-ref : 该属性指定一个已经存在的切入点名称,通常pointcut和pointcut-ref两个属性只需要使用其中之一。

                ⊙ method : 该属性指定一个方法名,指定该切面Bean的该方法转换为增强处理。

                ⊙ throwing : 该属性只对<after-throwing.../>元素有效,用于指定一个形参名,AfterThrowing增强处理方法可通过该形参访问目标方法所抛出的异常。

                ⊙ returning : 该属性只对<after-returning.../>元素有效,用于指定一个形参名,AfterReturning增强处理方法可通过该形参访问目标方法的返回值。

              当定义切入点表达式时,XML配置方式和@AspectJ注解方式支持完全相同的切入点指示符,一样可以支持execution、within、args、this、target和bean等切入点指示符。

              XML配置方式和@AspectJ注解方式一样支持组合切入点表达式,但XML配置方式不再使用简单的&&、|| 和 ! 作为组合运算符(因为直接在XML文件中需要使用实体引用来表示它们),而是使用如下三个组合运算符:and、or和not。

              Class : 删除Annotation注释--FourAdviceTest

    package edu.pri.lime._8_4_6.xmlaspect;
    
    import java.util.Arrays;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class FourAdviceTest {
    
        public Object processTx(ProceedingJoinPoint jp) throws Throwable{
            System.out.println("Around 增强 : 执行目标方法之前,模拟开始事务...");
            Object[] args = jp.getArgs();
            if(null != args && args.length > 0 && args[0].getClass() == String.class){
                args[0] = "【增加的前缀】" + args[0];
            }
            Object rvt = jp.proceed(args);
            System.out.println("Around 增强 : 执行目标方法后,模拟结束事务...");
            if(null != rvt && rvt instanceof Integer){
                rvt = (Integer)rvt * (Integer)rvt;
            }
            return rvt;
        }
        
        public void authorith(JoinPoint jp){
            System.out.println("Before 增强 : 模拟执行权限检查");
            System.out.println("Before 增强 : 被织入增强处理的目标方法为 : " + jp.getSignature().getName());
            System.out.println("Before 增强 : 目标方法的参数为 : " + Arrays.toString(jp.getArgs()));
            System.out.println("Before 增强 : 被织入增强处理的目标对象为 : " + jp.getTarget());
            System.out.println("Before 增强 : AOP框架为目标对象生成的代理对象为 : " + jp.getThis());
        }
        
        public void log(JoinPoint jp,Object rvt){
            System.out.println("AfterReturning 增强 : 获取目标方法返回值 : " + rvt);
            System.out.println("AfterReturning 增强 : 模拟记录日志功能...");
            System.out.println("AfterReturning 增强 : 被织入增强处理的目标方法为 : " + jp.getSignature().getName());
            System.out.println("AfterReturning 增强 : 目标方法的参数为 : " + Arrays.toString(jp.getArgs()));
            System.out.println("AfterReturning 增强 : 被织入增强处理的目标对象为 : " + jp.getTarget());
            System.out.println("AfterReturning 增强 : AOP框架为目标对象生成的代理对象为  : " + jp.getThis());
        }
        
        public void release(JoinPoint jp){
            System.out.println("After 增强 : 模拟方法结束后的释放资源...");
            System.out.println("After 增强 : 被织入增强处理的目标方法为 : " + jp.getSignature().getName());
            System.out.println("After 增强 : 目标方法的参数为 : " + Arrays.toString(jp.getArgs()));
            System.out.println("After 增强 : 被织入增强处理的目标对象为 : " + jp.getTarget());
            System.out.println("After 增强 : AOP框架为目标对象生成的代理对象为  : " + jp.getThis());
        }
    }

              Class : SecondAdviceTest

    package edu.pri.lime._8_4_6.xmlaspect;
    
    public class SecondAdviceTest {
    
    //    视图通过该arg形参来访问目标方法的参数值,这需要在配置该切面Bena时使用args切入点指示符
        public void authorith(String arg){
            System.out.println("目标方法的参数为 : " + arg);
            System.out.println("①号Before增强 : 模拟执行权限检查");
        }
    }

              XML : 

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:P="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <aop:config>
            <aop:aspect id="fourAdviceAspect" ref="fourAdviceBean"
                order="2">
                <!-- 定义一个Around增强处理 直接指定切入点表达式 以切面Bean中的processTx()方法作为增强处理方法 -->
                <aop:around method="processTx"
                    pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..))" />
                <!-- 定义一个Before增强处理 直接指定切入点表达式 以切面Bean中的authority()方法作为增强处理方法 -->
                <aop:before method="authority"
                    pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..))" />
                <!-- 定义一个AfterReturning增强处理 直接指定切入点表达式 以切面Bean中的log()方法作为增强处理方法 -->
                <aop:after-returning method="log"
                    pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..))"
                    returning="rvt" />
                <!-- 定义一个After增强 直接指定切入点表达式 以切面Bean中的release()方法作为增强处理方法 -->
                <aop:after method="release"
                    pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..))" />
            </aop:aspect>
            <!-- 将secondAdviceBean转换成切面Bean 切面Bean的新名称为:secondAdviceAspect 指定该切面的优先级为1,该切面里的增强处理将被有限织入 -->
            <aop:aspect id="secondAdviceAspect" ref="secondAdviceBean"
                order="1">
                <aop:before method="authority"
                    pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..)) and args(arg)" />
            </aop:aspect>
        </aop:config>
    
        <bean id="hello" class="edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl" />
    
        <bean id="fourAdviceBean" class="edu.pri.lime._8_4_6.xmladvice.FourAdviceTest" />
    
        <bean id="secondAdviceBean" class="edu.pri.lime._8_4_6.xmladvice.SecondAdviceTest" />
    </beans>

              Class : AspectTest

    package edu.pri.lime._8_4_6.xmladvice.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import edu.pri.lime._8_4_6.xmladvice.bean.Hello;
    
    public class AspectTest {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("app_8_4_6_advice.xml");
            Hello hello = (Hello) ctx.getBean("hello");
            hello.foo();
            System.out.println("--------------Bang bang, he shot me down----------------");
            hello.addUser("lime", "1234");
            System.out.println("--------------C'est la vie----------------");
            hello.deleteUser("lime");
        }
    }

              Console : 

    Around 增强 : 执行目标方法之前,模拟开始事务...
    22:03:38.837 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'Before 增强 : 模拟执行权限检查
    ② Before 增强 : 被织入增强处理的目标方法为 : foo
    ② Before 增强 : 目标方法的参数为 : []
    ② Before 增强 : 被织入增强处理的目标对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    ② Before 增强 : AOP框架为目标对象生成的代理对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    调用HelloImpl组件的foo()方法...
    Around 增强 : 执行目标方法后,模拟结束事务...
    22:03:38.840 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    AfterReturning 增强 : 获取目标方法返回值 : null
    AfterReturning 增强 : 模拟记录日志功能...
    AfterReturning 增强 : 被织入增强处理的目标方法为 : foo
    AfterReturning 增强 : 目标方法的参数为 : []
    AfterReturning 增强 : 被织入增强处理的目标对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    AfterReturning 增强 : AOP框架为目标对象生成的代理对象为  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    22:03:38.840 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    After 增强 : 模拟方法结束后的释放资源...
    After 增强 : 被织入增强处理的目标方法为 : foo
    After 增强 : 目标方法的参数为 : []
    After 增强 : 被织入增强处理的目标对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    After 增强 : AOP框架为目标对象生成的代理对象为  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    --------------Bang bang, he shot me down----------------
    22:03:38.841 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    Around 增强 : 执行目标方法之前,模拟开始事务...
    22:03:38.841 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    ② Before 增强 : 模拟执行权限检查
    ② Before 增强 : 被织入增强处理的目标方法为 : addUser
    ② Before 增强 : 目标方法的参数为 : [【增加的前缀】lime, 1234]
    ② Before 增强 : 被织入增强处理的目标对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    ② Before 增强 : AOP框架为目标对象生成的代理对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    调用HelloImpl组件的addUser()方法添加用户 : 【增加的前缀】lime
    Around 增强 : 执行目标方法后,模拟结束事务...
    22:03:38.841 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    AfterReturning 增强 : 获取目标方法返回值 : 484
    AfterReturning 增强 : 模拟记录日志功能...
    AfterReturning 增强 : 被织入增强处理的目标方法为 : addUser
    AfterReturning 增强 : 目标方法的参数为 : [【增加的前缀】lime, 1234]
    AfterReturning 增强 : 被织入增强处理的目标对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    AfterReturning 增强 : AOP框架为目标对象生成的代理对象为  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    22:03:38.841 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    After 增强 : 模拟方法结束后的释放资源...
    After 增强 : 被织入增强处理的目标方法为 : addUser
    After 增强 : 目标方法的参数为 : [【增加的前缀】lime, 1234]
    After 增强 : 被织入增强处理的目标对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    After 增强 : AOP框架为目标对象生成的代理对象为  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    --------------C'est la vie----------------
    22:03:38.849 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'secondAdviceBean'
    目标方法的参数为 : lime
    ① Before增强 : 模拟执行权限检查
    22:03:38.850 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    Around 增强 : 执行目标方法之前,模拟开始事务...
    22:03:38.850 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    ② Before 增强 : 模拟执行权限检查
    ② Before 增强 : 被织入增强处理的目标方法为 : deleteUser
    ② Before 增强 : 目标方法的参数为 : [【增加的前缀】lime]
    ② Before 增强 : 被织入增强处理的目标对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    ② Before 增强 : AOP框架为目标对象生成的代理对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    调用HelloImpl组件的deleteUser()方法删除用户 : 【增加的前缀】lime
    Around 增强 : 执行目标方法后,模拟结束事务...
    22:03:38.850 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    AfterReturning 增强 : 获取目标方法返回值 : 54756
    AfterReturning 增强 : 模拟记录日志功能...
    AfterReturning 增强 : 被织入增强处理的目标方法为 : deleteUser
    AfterReturning 增强 : 目标方法的参数为 : [【增加的前缀】lime]
    AfterReturning 增强 : 被织入增强处理的目标对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    AfterReturning 增强 : AOP框架为目标对象生成的代理对象为  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    22:03:38.850 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
    After 增强 : 模拟方法结束后的释放资源...
    After 增强 : 被织入增强处理的目标方法为 : deleteUser
    After 增强 : 目标方法的参数为 : [【增加的前缀】lime]
    After 增强 : 被织入增强处理的目标对象为 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
    After 增强 : AOP框架为目标对象生成的代理对象为  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0

            3.配置切入点

              XML配置方式也可以通过定义切入点来重用切入点表达式,Spring提供了<aop:pointcut.../>元素来定义切入点。

              当把<aop:pointcut.../>元素作为<aop:config.../>的子元素定义时,表明该切入点可别多个切面共享;

              当把<aop:pointcut.../>元素作为<aop:aspect.../>的子元素定义时,表明该切入点只能在切面中有效;

              配置<aop:pointcut.../>元素时通常需要指定如下两个属性:

                ⊙ id : 指定该切入点的标识名;

                ⊙ expression : 指定该切入点关联的切入点表达式;

              配置切入点表达式Demo : 

        <aop:config>
            <aop:pointcut expression="execution(* edu.pri.lime._8_4_6.pointcut.demo.bean.impl.*.*(..))" id="myPointcut"/>
        </aop:config>

              配置已有的切入点Demo :

        <aop:config>
            <aop:pointcut expression="edu.pri.lime._8_4_6.pointcut.demo.SystemArchitecture.myPointcut()" id="myPointcut"/>
        </aop:config>

              Class : RepairAspect

    package edu.pri.lime._8_4_6.pointcut;
    
    public class RepairAspect {
    
        public void doRecoveryActions(Throwable ex){
            System.out.println("目标方法中抛出的异常 : " + ex);
            System.out.println("模拟Advice对异常的修复...");
        }
    }

              XML : 

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:P="http://www.springframework.org/schema/p"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <bean id="hello" class="edu.pri.lime._8_4_6.pointcut.bean.impl.HelloImpl"/>
        <bean id="repairAspect" class="edu.pri.lime._8_4_6.pointcut.RepairAspect"/>
    
        <aop:config>
            <aop:pointcut expression="execution(* edu.pri.lime._8_4_6.pointcut.bean.impl.*.*(..))" id="myPointcut"/>
            <aop:aspect id="afterThrowingAdviceBean" ref="repairAspect">
                <aop:after-throwing method="doRecoveryActions" pointcut-ref="myPointcut" throwing="ex"/>
            </aop:aspect>
        </aop:config>
    </beans>

              Class : PointcutTest

    package edu.pri.lime._8_4_6.pointcut.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import edu.pri.lime._8_4_6.pointcut.bean.Hello;
    
    public class PointcutTest {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("app_8_4_6_pointcut.xml");
            Hello hello = (Hello) ctx.getBean("hello");
            hello.addUser("li", "2345");
        }
    }

              Console : 

    调用组件的addUser方法添加用户 : li
    22:44:03.511 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'repairAspect'
    目标方法中抛出的异常 : java.lang.IllegalArgumentException: name 长度小于3 或 大于10 
    模拟Advice对异常的修复...
    Exception in thread "main" java.lang.IllegalArgumentException: name 长度小于3 或 大于10 
        at edu.pri.lime._8_4_6.pointcut.bean.impl.HelloImpl.addUser(HelloImpl.java:16)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
        at com.sun.proxy.$Proxy2.addUser(Unknown Source)
        at edu.pri.lime._8_4_6.pointcut.main.PointcutTest.main(PointcutTest.java:13)

    啦啦啦

    啦啦啦

    啦啦啦

    啦啦啦

  • 相关阅读:
    爬虫(七):爬取猫眼电影top100
    爬虫(六):Selenium库使用
    爬虫(五):PyQuery的使用
    爬虫(四):BeautifulSoup库的使用
    爬虫(三):Requests库的基本使用
    爬虫(一):基本原理
    爬虫(二):Urllib库详解
    安装mongodb
    利用 Chromium Embedded Framework (CEF) 定制提取 Flash 视频的浏览器
    Flash Player 19.0.0.124 Beta + IHTMLDocument3 IHTMLDocument2 ->get_innerHTML
  • 原文地址:https://www.cnblogs.com/ClassNotFoundException/p/6476599.html
Copyright © 2020-2023  润新知