Java Config.class中的CacheManager bean定义导致NoSuchBeanDefinitionException

Java Config.class中的CacheManager bean定义导致NoSuchBeanDefinitionException,java,eclipselink,spring-data-jpa,spring-cache,Java,Eclipselink,Spring Data Jpa,Spring Cache,我有一个Spring服务,它检查数据库条目。为了最小化我的存储库调用,两个find方法都是“@Cacheable”。但当我尝试在配置类具有CacheManager bean定义的情况下初始化服务bean时,我得到以下NoSuchBeanDefinitionException: Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'foo.med

我有一个Spring服务,它检查数据库条目。为了最小化我的存储库调用,两个find方法都是“@Cacheable”。但当我尝试在配置类具有CacheManager bean定义的情况下初始化服务bean时,我得到以下NoSuchBeanDefinitionException:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'foo.mediacode.directory.MediaCodeDirectoryService' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:353)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1093)
at foo.mediacode.directory.MediaCodeDirectoryService.implementation(MediaCodeDirectoryService.java:63)
at foo.campaigntree.directory.CampaignTreeDirectoryService.<init>(CampaignTreeDirectoryService.java:18)
... 15 more
服务

....
    public class MediaCodeDirectoryService implements MediaCodeDirectoryServiceApi {

        ...

        @Autowired
        private MediaCodeDirectoryRepository repo;

        @SuppressWarnings("resource")
        public static MediaCodeDirectoryServiceApi implementation() {
        if (INSTANCE == null) {
                ApplicationContext ctx = new AnnotationConfigApplicationContext(MediaCodeDirectoryServiceConfig.class);
                INSTANCE = ctx.getBean(MediaCodeDirectoryService.class);
            }

            return INSTANCE;
        }
...
存储库

...
@Repository
public interface MediaCodeDirectoryRepository extends CrudRepository<MediaCodeDao, Integer> {

    @Cacheable("mediaCodeMappingRegexes")
    @Query("SELECT m FROM  #{#entityName} m WHERE (m.fooId = :fooId) AND (m.isRegex = :isRegex) ORDER BY (m.orderId DESC, m.id ASC)")
    List<MediaCodeDao> findByfooIdAndIsRegexOrderByOrderIdDescAndIdAsc(@Param("fooId") int fooId, @Param("isRegex") boolean isRegex);

    @Cacheable("mediaCodeMappings")
    List<MediaCodeDao> findByMediaCode(String MediaCode, Pageable pageable);
}
我避免了NosuchBeanDefinition异常,但遇到了另一个异常


这里有人知道这可能是什么原因吗?我的配置中有什么遗漏吗?谢谢

缓存通过AOP应用。对于AOP,Spring使用基于代理的方法,默认方法是创建基于接口的代理

public class MediaCodeDirectoryService implements MediaCodeDirectoryServiceApi {... }
在运行时使用此类定义,您将获得一个动态创建的类(
Proxy$51
或类似的类),该类实现了所有接口,但它不是
MediaCodeDirectoryService
。但是,它是一个
MediaCodeDirectoryServiceApi

有两种方法可以解决这个问题,一种是程序到接口(因为已经定义了接口,所以无论如何都应该这样做),而不是具体的类,另一种是使用基于类的代理

第一个选项涉及在直接
@Autowire
的位置更改代码,或者获取
MediaCodeDirectoryService
的实例以使用
MediaCodeDirectoryServiceApi
(您应该已经这样做了,为什么还要定义接口)。现在您将注入代理,一切都将正常工作

第二个选项涉及在
@EnableCaching
注释上设置
proxyTargetClass=true
。然后,您将得到一个基于类的代理,而不是基于接口的代理

@EnableCaching(proxyTargetClass=true)

您应该编程到接口而不是具体的类。。。因此,不要在代码中使用
MediaCodeDirectoryService
而是使用
MediaCodeDirectoryServiceApi
。在另一个节点上,您的代码是危险的,您永远不应该调用
new*ApplicationContext
,因为您基本上是在反复创建应用程序。如果你在很多地方都有这段代码,你最终会遇到内存问题、事务问题、奇怪的并发性问题(当然,如果你想让这些问题自由出现,但我强烈建议你不要这样做!)。非常感谢你清晰而详细的回答。之后,我做了一些研究,发现了为什么要自动连接接口而不是类的一般解释
public class MediaCodeDirectoryService implements MediaCodeDirectoryServiceApi {... }
@EnableCaching(proxyTargetClass=true)