我在使用基于Spring Data的应用程序在我的环境中运行时遇到问题。我正在运行Debian,但我的同事正在使用Mac或Ubuntu。我的环境变量中没有任何特殊设置,并且使用与其他版本完全相同的Java版本。
我在日志中看到过这种情况,这表明这是一个导致实例化失败的循环引用问题:
nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'flyway.CONFIGURATION_PROPERTIES':
Initialization of bean failed;
...
nested exception is
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'flyway': Requested bean is currently in
creation: Is there an unresolvable circular reference?
所以问题似乎是飞路需要一些依赖,他们需要飞路。
问题是,为什么这只发生在我的环境而不是任何人?即使在内存中使用H2的测试中,我也看到了问题,因此不是我的数据库出错了。
Spring自动装配是否有可能以某种方式混淆,并尝试以错误的顺序执行操作,以便在尝试设置存储库时为null?
对于排序依赖项,Spring是否有严格实现的拓扑排序?
为什么我的环境会出错?
类路径的排序是否会影响其行为?
======================
应用程序不会以此错误开头:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contentItemRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Repository interface must not be null on initialization!
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:175)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:127)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1517)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:251)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1127)
============================
ContentItemRepository签名是:
@Repository
@Transactional
public interface ContentItemRepository extends JpaRepository<ContentItem, String>, JpaSpecificationExecutor<ContentItem> {
============================
这曾经为我工作,我能够识别破坏构建的提交,通过遍历所有提交,执行mvn clean安装,并尝试启动服务器,直到我发现破坏它的delta
不能为null的'contentItemRepository'就是这个:
@Component
+public class UrlAliasRequestConverter implements Mapper<UrlAliasRequest, UrlAlias> {
+
+ /**
+ * The content item contentItemType repository.
+ */
+ @Autowired
+ private ContentItemRepository contentItemRepository;
答案 0 :(得分:5)
我在Ubuntu 16.04上遇到了同样的问题。
我发现
的问题@ComponentScan(basePackages = "com.my.app")
代码运行至少5台不同的机器(windows,ubuntu 15.04和ubuntu 16.04桌面)但是没有启动我们的CI服务器(ubuntu 16.04服务器)。
我改变了
@ComponentScan(basePackages = "com.my.app")
到
@ComponentScan(basePackages = {"com.my.app.service", "com.my.app.config", "com.my.app"})
代码也在CI服务器上运行。
我认为这是bean加载器的一个Spring问题......
<强>更新强>
答案 1 :(得分:4)
这很可能与行
中读取类文件的顺序有关 dir.listFiles()
in
PathMatchingResourcePatternResolver.doRetrieveMatchingFiles()
由于文件列表(类文件)的顺序依赖于平台,并且没有对数组进行排序,因此加载类的顺序取决于平台如何返回它们。
答案 2 :(得分:2)
您的存储库界面扩展了什么?您可以查看Spring源代码并查看抛出异常的原因:
@SuppressWarnings("unchecked")
public Class<? extends T> getObjectType() {
return (Class<? extends T>) (null == repositoryInterface ? Repository.class : repositoryInterface);
}
以下是我的存储库的一个示例:
@Repository
public interface GameRepository extends JpaRepository<Game, Long> {
答案 3 :(得分:2)
我不明白为什么会这样,但这是我提出的唯一解决方案:
安装Debian 8,它可以工作。
我在Debian 7的另一个干净安装中尝试了它,并且在那里得到的错误更少,但仍然有一些。干净的Debian 8安装似乎有效。
我只能得出结论,Java必须调用某个系统库,这在某种程度上会影响Spring依赖关系的解析顺序。该库必须在Debian 8中升级,使我能够使用其他开发人员和生产者正在使用的Ubuntu安装。
我不知道那个库可能是什么...扫描文件系统中的文件,以不同的顺序报告它们的东西?解压缩.jar文件,以不同的顺序报告其内容的东西?
我觉得我们的代码对依赖关系解析和注入的确切顺序非常敏感似乎是错的,但事实似乎就是这样。看起来我们的代码中没有任何东西可以使它对排序敏感,我们没有做任何疯狂的事情,并遵循非常标准的使用模式。
如果你问我,太多的魔法会保持卡片的立场。我的其他项目是在DropWizard上,并且依赖注入是手动编码的,所以没有意外。
===更新
我将Debian 7框升级为8,问题仍然存在。因此,我关于它是库版本的假设是错误的。必须是我的环境。
我在盒子上创建了一个新用户。该用户仍然存在问题。这个盒子有一些它真的不喜欢,但我无法弄清楚它是什么。
我想了解真正的事业并理解它,但我认为我不能再花时间去解决它。
无论如何,彻底安装Debian 8解决了这个问题。
答案 4 :(得分:2)
昨天我遇到了同样的问题。我不知道为什么,但我找到了解决问题的方法:将循环依赖树中涉及的所有bean标记为lazy-init
。不仅是直接相互依赖的那些,而是所有引用它们的bean!
该项目是一个旧项目,因此它只使用弹簧3.我不确定更高版本的弹簧是否仍然会出现这个问题。
答案 5 :(得分:1)
我不知道为什么这个特定问题会在一台机器而不是另一台机器上发生,但我认为问题很可能是两个bean都使用构造函数注入来传递彼此的引用,这会创建无法解析的循环依赖--A需要B来构造它反过来需要A-既不能在没有创建其他的情况下创建。 如果两个对象都需要引用另一个对象,则需要在创建对象后通过setter注入传递它。 this question的答案与您遇到的问题相关。
答案 6 :(得分:1)
我们今天在几乎相同的情况下遇到了这个问题-应用程序由于循环引用而无法启动,显然是在构造Spring Data @Repository
实例时,并且仅在一个开发人员的机器上。
在我们的案例中,解决方案是重构我们的配置,以使ApplicationListener<BeforeSaveEvent>
不再是@Configuration
类中定义的匿名类,而变成了顶级@Component
似乎Spring Data储存库以某种非显而易见的方式对这些应用程序侦听器进行了某种处理,并且通过将我们的数据库作为匿名内部类,该储存库隐式维护了对其封闭@Configuration
的引用(因此,由于通过@Configuration
实例化了bean并最终自动连接存储库而检测到依赖项循环。
所有描述更改惰性初始化,更改组件扫描顺序,重新安装操作系统,关闭并再次打开等的答案都只是隐藏而不是真正解决问题,我建议您从源头上修复它:)在@xki暗示下,对象图在构造上的不确定性是不确定的。
答案 7 :(得分:0)
对我们来说,问题在于CPU利用率很高,而且这个错误似乎一无是处。
在linux中运行以下命令以查找cpu利用率:
top -b -n1 | grep ^%Cpu | awk '{cpu+=$9}END{print "Current CPU Utilization is : " 100-cpu/NR}'
如果它是100或接近100,则意味着我们必须杀死其他一些当前未使用的微服务或升级我们的系统容量。
答案 8 :(得分:0)
尽管所有答案都集中在故障机器及其修复方法上,但我想指出,我们应该对没有故障的机器感到疑惑。如果有一个循环,则DI应该会失败!我们希望在所有环境中都能做到这一点。
我们遇到了相同的行为,即生产失败,但暂存,dev和CI都很好。真伤心我们无法针对该问题创建一个最小的示例。
答案 9 :(得分:0)
临时拐杖解决方案:ENV spring.main.lazy-initialization=true