【问题标题】:Spring AOP : How to fix this bugSpring AOP:如何修复此错误
【发布时间】:2014-07-17 05:00:09
【问题描述】:

我正在练习 AOP 并在简单的 AOP 示例中遇到错误。这似乎是与 Jar 版本相关的问题。 我已经包含了所有必要的 JAR CGLib-2.1,aspectjrt-1.6.0,aspectj-1.6.9,aopalliance-1.0.jar

代码如下:

**

  • Beans.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
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

       <aop:config>
          <aop:aspect id="log" ref="logging">
             <aop:pointcut id="selectAll" 
             expression="execution(* com.tutorialspoint.*.*(..))"/>
             <aop:before pointcut-ref="selectAll" method="beforeAdvice"/>
             <aop:after pointcut-ref="selectAll" method="afterAdvice"/>
             <aop:after-returning pointcut-ref="selectAll" 
                                  returning="retVal"
                                  method="afterReturningAdvice"/>
             <aop:after-throwing pointcut-ref="selectAll" 
                                 throwing="ex"
                                 method="AfterThrowingAdvice"/>
          </aop:aspect>
       </aop:config>

       <!-- Definition for student bean -->
       <bean id="student" class="com.tutorialpoint.Student">
          <property name="name"  value="Zara" />
          <property name="age"  value="11"/>      
       </bean>

       <!-- Definition for logging aspect -->
       <bean id="logging" class="com.tutorialpoint.Logging"/> 


</beans>

**

  • Lo​​gging.java

**

package com.tutorialpoint;

public class Logging {

   /** 
    * This is the method which I would like to execute
    * before a selected method execution.
    */
   public void beforeAdvice(){
      System.out.println("Going to setup student profile.");
   }

   /** 
    * This is the method which I would like to execute
    * after a selected method execution.
    */
   public void afterAdvice(){
      System.out.println("Student profile has been setup.");
   }

   /** 
    * This is the method which I would like to execute
    * when any method returns.
    */
   public void afterReturningAdvice(Object retVal){
      System.out.println("Returning:" + retVal.toString() );
   }

   /**
    * This is the method which I would like to execute
    * if there is an exception raised.
    */
   public void AfterThrowingAdvice(IllegalArgumentException ex){
      System.out.println("There has been an exception: " );   
   }

}

Main.java

package com.tutorialpoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
   public static void main(String[] args) {
      ApplicationContext context = 
             new ClassPathXmlApplicationContext("Beans.xml");

      Student student = (Student) context.getBean("student");

      student.getName();
      student.getAge();

      student.printThrowException();
      System.out.println("helloee");
   }
}

学生.java

package com.tutorialpoint;

public class Student {
   private Integer age;
   private String name;

   public void setAge(Integer age) {
      this.age = age;
   }
   public Integer getAge() {
      System.out.println("Age : " + age );
      return age;
   }

   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      System.out.println("Name : " + name );
      return name;
   }

   public void printThrowException(){
       System.out.println("Exception raised");
       throw new IllegalArgumentException();
   }
}

控制台输出

Jul 16, 2014 8:44:36 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@63c12fb0: startup date [Wed Jul 16 20:44:36 BST 2014]; root of context hierarchy
Jul 16, 2014 8:44:36 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [Beans.xml]
Jul 16, 2014 8:44:36 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6d4b1c02: defining beans [org.springframework.aop.config.internalAutoProxyCreator,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0,org.springframework.aop.aspectj.AspectJPointcutAdvisor#1,org.springframework.aop.aspectj.AspectJPointcutAdvisor#2,org.springframework.aop.aspectj.AspectJPointcutAdvisor#3,selectAll,student,logging]; root of factory hierarchy
Jul 16, 2014 8:44:37 PM org.springframework.beans.factory.support.DefaultListableBeanFactory destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6d4b1c02: defining beans [org.springframework.aop.config.internalAutoProxyCreator,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0,org.springframework.aop.aspectj.AspectJPointcutAdvisor#1,org.springframework.aop.aspectj.AspectJPointcutAdvisor#2,org.springframework.aop.aspectj.AspectJPointcutAdvisor#3,selectAll,student,logging]; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.aspectj.AspectJPointcutAdvisor#2': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.aop.aspectj.AspectJPointcutAdvisor]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:288)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1049)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:953)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.tutorialpoint.Main.main(Main.java:9)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.aop.aspectj.AspectJPointcutAdvisor]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:121)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:280)
    ... 14 more
Caused by: java.lang.IllegalArgumentException
    at org.springframework.asm.ClassReader.<init>(Unknown Source)
    at org.springframework.asm.ClassReader.<init>(Unknown Source)
    at org.springframework.asm.ClassReader.<init>(Unknown Source)
    at org.springframework.core.LocalVariableTableParameterNameDiscoverer.inspectClass(LocalVariableTableParameterNameDiscoverer.java:110)
    at org.springframework.core.LocalVariableTableParameterNameDiscoverer.getParameterNames(LocalVariableTableParameterNameDiscoverer.java:72)
    at org.springframework.core.PrioritizedParameterNameDiscoverer.getParameterNames(PrioritizedParameterNameDiscoverer.java:53)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.bindArgumentsByName(AbstractAspectJAdvice.java:420)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.calculateArgumentBindings(AbstractAspectJAdvice.java:375)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.getPointcut(AbstractAspectJAdvice.java:176)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.buildSafePointcut(AbstractAspectJAdvice.java:186)
    at org.springframework.aop.aspectj.AspectJPointcutAdvisor.<init>(AspectJPointcutAdvisor.java:51)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
    ... 16 more

【问题讨论】:

  • 你的表达式有tutorialspoint,你的包名是tutorialpoint。解决这个问题有帮助吗?
  • 谢谢戴夫,这是一个错误,但错误堆栈中没有变化。

标签: java spring aop spring-aop aopalliance


【解决方案1】:

在检查类中的某些参数名称(retValex)时,它看起来像是崩溃了。当您在启用调试信息的情况下进行编译(javac-g 选项)时,此信息仅在 Java .class 文件中可用。你能检查你是否在启用调试信息的情况下进行编译?

来自Spring docs

确定参数名称

通知调用中的参数绑定依赖于切入点表达式中使用的名称与(通知和切入点)方法签名中声明的参数名称的匹配。参数名不能通过Java反射获得,所以Spring AOP使用以下策略来确定参数名:

  • 如果参数名称已由用户明确指定,则使用指定的参数名称:通知和切入点注释都有一个可选的“argNames”属性,可用于指定注释方法的参数名称- 这些参数名称在运行时可用...

  • 如果第一个参数是JoinPointProceedingJoinPointJoinPoint.StaticPart 类型,则可以在“argNames”属性的值中省略参数名称...

  • 使用 'argNames' 属性有点笨拙,所以如果 'argNames' 属性没有指定,那么 Spring AOP 会查看类的调试信息,并尝试从局部变量表中确定参数名称.只要类已使用调试信息编译(至少-g:vars),此信息就会出现...

  • 如果在没有必要调试信息的情况下编译了代码,那么 Spring AOP 将尝试推断绑定变量与参数的配对(例如,如果切入点表达式中只绑定了一个变量,并且advice 方法只取一个参数,配对很明显!)。如果给定可用信息的变量绑定不明确,则将抛出AmbiguousBindingException

  • 如果上述所有策略均失败,则将抛出 IllegalArgumentException

【讨论】:

  • 后退、后抛都有问题。
  • 我没有从 JAVAC -g 选项中得到任何具体信息。
猜你喜欢
  • 1970-01-01
  • 2020-02-22
  • 2014-03-01
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多