Spring AOP: как исправить эту ошибку

Я практикую 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>

**

  • Logging.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");
   }
}

Student.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();
   }
}

ConsoleOutput

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

1 ответ

Похоже, что происходит сбой при проверке класса для некоторых имен параметров (либо retVal или же ex). Эта информация доступна только в файлах Java.class, когда вы компилируете с включенной отладочной информацией (-g вариант для javac). Можете ли вы проверить, что вы компилируете с включенной отладочной информацией?

Из весенней документации:

Определение имен аргументов

Привязка параметров в вызовах подсказок основывается на сопоставлении имен, используемых в выражениях pointcut, с объявленными именами параметров в сигнатурах методов (advice и pointcut). Имена параметров не доступны через отражение Java, поэтому Spring AOP использует следующие стратегии для определения имен параметров:

  • Если имена параметров были заданы пользователем явно, то используются указанные имена параметров: аннотации advice и pointcut имеют необязательный атрибут "argNames", который можно использовать для указания имен аргументов аннотированного метода - эти аргументы имена доступны во время выполнения...

  • Если первый параметр имеет JoinPoint, ProceedingJoinPoint, или же JoinPoint.StaticPart типа, вы можете опустить имя параметра из значения атрибута "argNames"...

  • Использование атрибута 'argNames' немного неуклюже, поэтому, если атрибут 'argNames' не указан, Spring AOP будет искать отладочную информацию для класса и попытаться определить имена параметров из таблицы локальных переменных. Эта информация будет присутствовать, пока классы скомпилированы с отладочной информацией (-g:vars минимум)...

  • Если код был скомпилирован без необходимой отладочной информации, то Spring AOP попытается определить сопряжение переменных привязки с параметрами (например, если в выражении pointcut связана только одна переменная, а метод advice принимает только один параметр, спаривание очевидно!). Если привязка переменных неоднозначна с учетом доступной информации, то AmbiguousBindingException будет брошен.

  • Если все вышеперечисленные стратегии терпят неудачу, то IllegalArgumentException будет брошен.

Другие вопросы по тегам