简体   繁体   English

spring-data-neo4j与Autowired冲突

[英]spring-data-neo4j conflict with Autowired

so I have a project that use spring-data-neo4j and met a obscure problem. 所以我有一个使用spring-data-neo4j的项目,遇到了一个模糊的问题。 I use java config for spring-neo4j,Neo4jConfig.java: 我对spring-neo4j,Neo4jConfig.java使用Java配置:

@Configuration
@EnableNeo4jRepositories(basePackages = "org.neo4j.example.repository")
@EnableTransactionManagement
public class Neo4jConfig extends Neo4jConfiguration {

    @Bean
    public SessionFactory getSessionFactory() {
        // with domain entity base package(s)
        return new SessionFactory("org.neo4j.example.domain");
    }

    // needed for session in view in web-applications
    @Bean
    @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public Session getSession() throws Exception {
        return super.getSession();
    }

}

the I hava a DAO and one implements,BeanDaoImpl.java: 我有一个DAO和一个工具,BeanDaoImpl.java:

@Repository
public class BeanDaoImpl implements BeanDao {
    public String getStr() {
        return "from BeanImpl";
    }
}

then I have a service use the DaoImpl, note that the autowired is BeanDaoImpl,not BeanDao : 然后我有一个使用DaoImpl的服务, 请注意,自动装配的是BeanDaoImpl,而不是BeanDao

@Service
public class MyBeanService {
    @Autowired
    private BeanDaoImpl daoImpl;


    public String getServiceString(){
        return daoImpl.getStr();
    }
}

here is my app-context.xml: 这是我的app-context.xml:

    <context:component-scan base-package="com.springconflict" />

the version is springframework 4.2.5, spring-data-neo4j 4.1.11,it seems spring-data-neo4j has compatibility with spring 4.2.5; 版本是springframework 4.2.5,spring-data-neo4j 4.1.11,似乎spring-data-neo4j与spring 4.2.5兼容;

here is the compile error info: 这是编译错误信息:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.springconflict.dao.impl.BeanDaoImpl com.springconflict.service.MyBeanService.daoImpl; 引起原因:org.springframework.beans.factory.BeanCreationException:无法自动连线字段:私有com.springconflict.dao.impl.BeanDaoImpl com.springconflict.service.MyBeanService.daoImpl; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.springconflict.dao.impl.BeanDaoImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. 嵌套的异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:未找到类型为[com.springconflict.dao.dao.impl.BeanDaoImpl]的合格Bean作为依赖项:至少应有1个符合此依赖项的自动装配候选的bean。 Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 依赖项注释:{@ org.springframework.beans.factory.annotation.Autowired(required = true)}

The odds are either I remove Neo4jConfig or use @Autowired BeanDao the test can pass. 可能是我删除了Neo4jConfig或使用了可以通过测试的@Autowired BeanDao also, I use a common @Configuration class, the test still pass,so the problem may in Neo4jConfiguration , can someone tell me why and how to fix this? 另外,我使用普通的@Configuration类,测试仍然通过,因此Neo4jConfiguration可能存在问题,有人可以告诉我为什么以及如何解决此问题吗? I have no access to change @Autowired BeanDaoImpl to @Autowired BeanDao in real project. @Autowired BeanDao在实际项目@Autowired BeanDaoImpl @Autowired BeanDao更改为@Autowired BeanDao

all code are in here 所有代码都在这里

TL;DR Answer: Define the following additional bean in Neo4jConfig , thus overwriting SDN 4.x's default instance of PersistenceExceptionTranslationPostProcessor . TL; DR答:在Neo4jConfig定义以下其他bean,从而覆盖SDN 4.x的PersistenceExceptionTranslationPostProcessor的默认实例。

@Bean
PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
    PersistenceExceptionTranslationPostProcessor p = new PersistenceExceptionTranslationPostProcessor();
    p.setProxyTargetClass(true);
    return p;
}

Long answer: Spring Data Neo4j uses Springs PersistenceExceptionTranslationPostProcessor to remap Neo4j OGM exceptions into Spring Data exceptions. 长答案:Spring Data Neo4j使用Springs PersistenceExceptionTranslationPostProcessor将Neo4j OGM异常重新映射为Spring Data异常。 Those processor is applied to all components of type @Repository . 这些处理器适用于@Repository类型的所有组件。

So the post processor forms now a proxy around your BeanDoaImpl and thus it's basically like another class. 因此,后处理器现在在BeanDoaImpl周围形成一个代理,因此基本上就像另一个类。 That works fine if you use the interface, but not if you want to assign the bean to the concrete class. 如果您使用接口,那很好用,但是如果您想将bean分配给具体的类,那不是很好。

Spring can be configured globally to create subclasses instead of standard Java interface based proxies (it does that by use of CGLIB), but that's not on by default and in case of Spring 4.2.x and Spring Data Neo4j 4.2.x would not matter anyway, as the post processor above was independent from that mechanism. 可以将Spring全局配置为创建子类,而不是基于标准Java接口的代理(通过使用CGLIB来实现),但是默认情况下未启用它,并且在Spring 4.2.x和Spring Data Neo4j 4.2.x的情况下也没关系,因为上面的后处理器与该机制无关。

Replacing it with one explicitly configured solves your problem. 用一个明确配置的替代它可以解决您的问题。

From an architectural point of view (or clean code wise), it would be better if you would inject the interface, not the concrete class, though. 从体系结构的角度(或明智的编码方式)来看,最好是注入接口,而不注入具体的类。

Please let me know, if I could help you :) 如果可以帮助您,请告诉我:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM