AspectJ和NoSuchBeanDefinitionException至少有1个bean,它有资格作为此依赖项的autowire候选者

时间:2013-06-04 09:46:22

标签: spring aspectj

我正在尝试使用AspectJ,我的项目工作正常。但是当我尝试使用AspectJ时,注射不能正常工作。如果我不使用AspectJ,它会再次起作用。

我收录在我的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课程,无论如何我都做了。我试着将PlayerDAO标记为required = false,我可以检查是否调用了LoggingAspect但是当RoomDAO要调用PlayerDAO时,我得到了NullPointException。当我使用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.springframework.beans.factory.support.DefaultListableBeanFactory@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

谢谢。

更新:

我修复了添加

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

但是,我不知道为什么会发生这种情况,如果有人能解释我,我感激不尽。

2 个答案:

答案 0 :(得分:2)

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

  

Spring AOP使用JDK动态代理或CGLIB来创建   给定目标对象的代理。 (JDK动态代理是首选   只要你有选择)。

     

如果要代理的目标对象实现至少一个接口   然后将使用JDK动态代理。所有接口   由目标类型实现的代理将被代理。如果是目标对象   没有实现任何接口,那么将创建一个CGLIB代理。

     

如果要强制使用CGLIB代理(例如,代理   为目标对象定义的每个方法,而不仅仅是那些实现的方法   通过它的接口)你可以这样做。   ....   要强制使用CGLIB代理,请设置值   element的proxy-target-class属性为true:

因此,您已为所有类启用了CGLIB代理。阅读整个页面以获取更多信息 - 这是使用spring AOP的重要背景信息。使用CGLIB时会发生一些有趣且不同的事情(所有这些都记录在上面的链接中) - 如果可以的话,最好遵循Spring约定。即如果你自动装配一个类,给它一个接口和一个空构造函数。

答案 1 :(得分:0)

我错误地在一个单元测试中得到了相同的错误消息:

@Autowire
ServiceImpl service;

而不是

@Autowire
Service service;

(ServiceImpl正在实施Service)。它正在使用任何一个版本,直到我添加 aop:aspectj-autoproxy