spring-data-neo4j 与 Autowired 冲突
spring-data-neo4j conflict with Autowired
所以我有一个使用 spring-data-neo4j 的项目,遇到了一个难解的问题。
我对 spring-neo4j 使用 java 配置,Neo4jConfig.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();
}
}
我有一个 DAO 和一个实现,BeanDaoImpl.java:
@Repository
public class BeanDaoImpl implements BeanDao {
public String getStr() {
return "from BeanImpl";
}
}
然后我有一个使用 DaoImpl 的服务,注意自动装配的是 BeanDaoImpl,而不是 BeanDao:
@Service
public class MyBeanService {
@Autowired
private BeanDaoImpl daoImpl;
public String getServiceString(){
return daoImpl.getStr();
}
}
这是我的应用-context.xml:
<context:component-scan base-package="com.springconflict" />
版本是springframework 4.2.5,spring-data-neo4j 4.1.11,看来spring-data-neo4j和spring兼容4.2.5;
这里是编译错误信息:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private 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. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
可能性是我删除 Neo4jConfig
或使用 @Autowired BeanDao
测试可以通过。另外,我用的是普通的@Configuration
class,测试还是通过了,所以问题可能在Neo4jConfiguration
,有人能告诉我为什么以及如何解决这个问题吗?
我无法在实际项目中将 @Autowired BeanDaoImpl
更改为 @Autowired BeanDao
。
TL;DR 答案:在 Neo4jConfig
中定义以下附加 bean,从而覆盖 SDN 4.x 的默认实例 PersistenceExceptionTranslationPostProcessor
。
@Bean
PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
PersistenceExceptionTranslationPostProcessor p = new PersistenceExceptionTranslationPostProcessor();
p.setProxyTargetClass(true);
return p;
}
长答案:Spring Data Neo4j 使用 Springs PersistenceExceptionTranslationPostProcessor
将 Neo4j OGM 异常重新映射为 Spring Data 异常。这些处理器应用于 @Repository
类型的所有组件。
所以 post 处理器现在形成了围绕您的 BeanDoaImpl
的代理,因此它基本上就像另一个 class。如果您使用该接口,则效果很好,但如果您想将 bean 分配给具体 class.
,则效果不佳
Spring 可以全局配置以创建子 classes 而不是基于标准 Java 接口的代理(它通过使用 CGLIB 实现),但默认情况下不启用并且在 Spring 4.2.x 和 Spring Data Neo4j 4.2.x 的情况下无论如何都无关紧要,因为上面的 post 处理器独立于该机制.
用一个明确配置的替换它可以解决您的问题。
不过,从架构的角度(或干净的代码方面)来看,注入接口而不是具体的 class 会更好。
如果我能帮到你,请告诉我:)
所以我有一个使用 spring-data-neo4j 的项目,遇到了一个难解的问题。 我对 spring-neo4j 使用 java 配置,Neo4jConfig.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();
}
}
我有一个 DAO 和一个实现,BeanDaoImpl.java:
@Repository
public class BeanDaoImpl implements BeanDao {
public String getStr() {
return "from BeanImpl";
}
}
然后我有一个使用 DaoImpl 的服务,注意自动装配的是 BeanDaoImpl,而不是 BeanDao:
@Service
public class MyBeanService {
@Autowired
private BeanDaoImpl daoImpl;
public String getServiceString(){
return daoImpl.getStr();
}
}
这是我的应用-context.xml:
<context:component-scan base-package="com.springconflict" />
版本是springframework 4.2.5,spring-data-neo4j 4.1.11,看来spring-data-neo4j和spring兼容4.2.5;
这里是编译错误信息:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private 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. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
可能性是我删除 Neo4jConfig
或使用 @Autowired BeanDao
测试可以通过。另外,我用的是普通的@Configuration
class,测试还是通过了,所以问题可能在Neo4jConfiguration
,有人能告诉我为什么以及如何解决这个问题吗?
我无法在实际项目中将 @Autowired BeanDaoImpl
更改为 @Autowired BeanDao
。
TL;DR 答案:在 Neo4jConfig
中定义以下附加 bean,从而覆盖 SDN 4.x 的默认实例 PersistenceExceptionTranslationPostProcessor
。
@Bean
PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
PersistenceExceptionTranslationPostProcessor p = new PersistenceExceptionTranslationPostProcessor();
p.setProxyTargetClass(true);
return p;
}
长答案:Spring Data Neo4j 使用 Springs PersistenceExceptionTranslationPostProcessor
将 Neo4j OGM 异常重新映射为 Spring Data 异常。这些处理器应用于 @Repository
类型的所有组件。
所以 post 处理器现在形成了围绕您的 BeanDoaImpl
的代理,因此它基本上就像另一个 class。如果您使用该接口,则效果很好,但如果您想将 bean 分配给具体 class.
Spring 可以全局配置以创建子 classes 而不是基于标准 Java 接口的代理(它通过使用 CGLIB 实现),但默认情况下不启用并且在 Spring 4.2.x 和 Spring Data Neo4j 4.2.x 的情况下无论如何都无关紧要,因为上面的 post 处理器独立于该机制.
用一个明确配置的替换它可以解决您的问题。
不过,从架构的角度(或干净的代码方面)来看,注入接口而不是具体的 class 会更好。
如果我能帮到你,请告诉我:)