Spring Bean初始化失败:bound必须大于origin问题排查求助
异常信息
org.springframework.context.support.AbstractApplicationContext refresh
警告:上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.beans.factory.BeanCreationException: 创建类路径资源[application-context.xml]中定义的名为'loryCat'的Bean出错;Bean初始化失败;嵌套异常为java.lang.IllegalArgumentException: bound must be greater than origin
主线程中的异常:org.springframework.beans.factory.BeanCreationException: 创建类路径资源[application-context.xml]中定义的名为'loryCat'的Bean出错;Bean初始化失败;嵌套异常为java.lang.IllegalArgumentException: bound must be greater than origin
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:144)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:85)
at com.example.springcontext.Application.main(Application.java:7)
Caused by: java.lang.IllegalArgumentException: bound must be greater than origin
at java.base/jdk.internal.util.random.RandomSupport.checkRange(RandomSupport.java:232)
at java.base/java.util.random.RandomGenerator.nextInt(RandomGenerator.java:679)
at com.example.springcontext.CatStrengthCalculatorBeanPostProcessor.postProcessBeforeInitialization(CatStrengthCalculatorBeanPostProcessor.java:20)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:440)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
... 11 more
相关代码与配置
application-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.example.springcontext.CombatCat" id="loryCat"> <property name="name" value="Lori"/> </bean> <bean class="com.example.springcontext.CombatCat" id="baxterCat"> <property name="name" value="Baxter"/> </bean> <bean class="com.example.springcontext.FightClubImpl" id="fightClub"> <property name="loryCat" ref="loryCat"/> <property name="baxterCat" ref="baxterCat"/> </bean> <bean class="com.example.springcontext.CatStrengthCalculatorBeanPostProcessor"/> </beans>
CombatCat.java
package com.example.springcontext; public class CombatCat { private String name; @CalculateCatStrangth(minStrength = 10, maxStrength = 14) private Integer strangth; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getStrangth() { return strangth; } @Override public String toString() { return "CombatCat{" + "name='" + name + '\'' + ", strangth=" + strangth + '}'; } }
原因分析
- 异常根源是
CatStrengthCalculatorBeanPostProcessor的postProcessBeforeInitialization方法(第20行)调用RandomGenerator.nextInt()时,传入的参数违反了方法要求:bound必须大于origin。 - 结合
CombatCat的注解参数minStrength=10、maxStrength=14,可以确定是BeanPostProcessor中处理注解参数的逻辑错误,比如:- 调用
nextInt时参数顺序搞反(把max作为origin,min作为bound) - 计算随机值范围时逻辑错误,导致bound <= origin
- 调用
解决方法
修正随机数生成逻辑
打开CatStrengthCalculatorBeanPostProcessor.java,找到第20行的随机数生成代码,确保参数顺序和范围计算正确:- 若使用
RandomGenerator.nextInt(int origin, int bound)方法(生成[origin, bound)的整数),要生成[minStrength, maxStrength]的随机值,需传入minStrength作为origin,maxStrength + 1作为bound:int strength = random.nextInt(minStrength, maxStrength + 1); - 若使用单参数的
nextInt(int bound)方法,需先计算范围长度,再偏移到最小值:int range = maxStrength - minStrength + 1; int strength = random.nextInt(range) + minStrength;
- 若使用
添加参数合法性校验
在BeanPostProcessor中增加注解参数的校验逻辑,避免因注解配置错误(比如maxStrength <= minStrength)再次触发异常:CalculateCatStrangth annotation = field.getAnnotation(CalculateCatStrangth.class); int min = annotation.minStrength(); int max = annotation.maxStrength(); if (max <= min) { throw new IllegalArgumentException("maxStrength must be greater than minStrength for field: " + field.getName()); }
内容的提问来源于stack exchange,提问作者koba

