2013-06-04 62 views
2

我試圖使用AspectJ,我的項目工作正常。但是當我嘗試使用AspectJ時,注射不能正常工作。如果我不使用AspectJ,它會再次運行。AspectJ和NoSuchBeanDefinitionException至少有1個bean有資格作爲此依賴關係的自動導向候選者

我包括我的pom.xml

<dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-aop</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 

     <dependency> 
      <groupId>org.aspectj</groupId> 
      <artifactId>aspectjrt</artifactId> 
      <version>1.6.11</version> 
     </dependency> 

     <dependency> 
      <groupId>org.aspectj</groupId> 
      <artifactId>aspectjweaver</artifactId> 
      <version>1.6.11</version> 
     </dependency> 

我的配置文件:

<aop:aspectj-autoproxy /> 
    <tx:annotation-driven /> 

    <!-- Database Configuration --> 
    <import resource="../database/DataSource.xml"/> 

     <!-- Auto scan the components --> 
    <context:component-scan base-package="es.rooms.db.spring.dao" /> 
    <context:component-scan base-package="es.rooms.util" /> 

    <!-- Aspect --> 
    <bean id="logAspect" class="es.rooms.util.LoggingAspect" /> 

我使用註釋來我的班:

@Repository("RoomDAO") 
public class RoomDAO extends JdbcDaoSupport implements IRoomDAO{ 

    @Autowired 
    private PlayerDAO playerDAO; 

我不知道如果我必須掃描我的AspectJ課程,我無論如何。我試圖標記爲required = false PlayerDAO,我可以檢查LoggingAspect是否被調用,但是當RoomDAO打算調用PlayerDAO時,我得到了一個N​​ullPointException異常。爲什麼不能在我使用AspectJ的時候彈出注入PlayerDAO?

@Aspect 
public class LoggingAspect { 



    @Before("execution(* es.rooms.db.spring.dao.*.*(..))") 
    public void logBefore(JoinPoint joinPoint) { 

     System.out.println("!!!!!!!!!!!!!!logBefore() is running! ->" + joinPoint.getSignature().getName());   
     System.out.println("******"); 
    } 

這是錯誤:

04-jun-2013 11:36:46 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons 
INFO: Destroying singletons in org.s[email protected]61acfa31: defining beans [org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,dataSource,playerDAO,RoomDAO,userDAO,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,manageRooms,messagesGcm,transactionManager,logAspect,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy 
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'RoomDAO': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private es.rooms.db.spring.dao.PlayerDAO es.rooms.db.spring.dao.RoomDAO.playerDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [es.rooms.db.spring.dao.PlayerDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) 
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139) 
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83) 
    at es.rooms.server.RoomsServer.<init>(RoomsServer.java:23) 
    at es.rooms.server.RoomsServer.main(RoomsServer.java:61) 
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private es.rooms.db.spring.dao.PlayerDAO es.rooms.db.spring.dao.RoomDAO.playerDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [es.rooms.db.spring.dao.PlayerDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284) 
    ... 14 more 

謝謝。

UPDATE:

我固定它添加

<aop:aspectj-autoproxy proxy-target-class="true"/> 

但是,我不知道爲什麼發生這種情況,我很感激,如果有人可以解釋我。

+2

有一件事我看到可能會影響它的是,你的autowire應該使用接口IPlayerDAO,而不是實現。我相信當Spring創建代理時,它使用接口來構建它,然後調用實例化的類。我將這一觀察僅僅基於我在自己的代碼中看到的堆棧跟蹤,所以我可能是錯的。 – CodeChimp

+0

哦!非常感謝!你是對的。我刪除了autoproxy標籤,它正在工作。 – Guille

+0

@CodeChimp:非常感謝你的解決方案,我有同樣的問題,花了幾天的堅果,終於找到了這篇文章.... :) –

回答

2
http://docs.spring.io/spring/docs/3.1.1.RELEASE/spring-framework-reference/html/aop.html

Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given target object. (JDK dynamic proxies are preferred whenever you have a choice).

If the target object to be proxied implements at least one interface then a JDK dynamic proxy will be used. All of the interfaces implemented by the target type will be proxied. If the target object does not implement any interfaces then a CGLIB proxy will be created.

If you want to force the use of CGLIB proxying (for example, to proxy every method defined for the target object, not just those implemented by its interfaces) you can do so. .... To force the use of CGLIB proxies set the value of the proxy-target-class attribute of the element to true:

所以,你必須開啓所有類的CGLIB代理。閱讀整個頁面以獲取更多信息 - 這是使用彈簧AOP的重要背景信息。當你使用CGLIB時,會發生一些有趣和不同的事情(所有文檔都在上面的鏈接中) - 如果可以的話,最好遵循Spring約定。即如果你自動裝載一個類,給它一個接口和一個空的構造函數。

0

我結束了相同的錯誤消息在我使用的一個單元測試,誤:

@Autowire 
ServiceImpl service; 

代替

@Autowire 
Service service; 

(其中ServiceImpl正在執行服務)。直到我加入aop:aspectj-autoproxy

相關問題