Spring中@Required注解已赋值仍抛出Bean属性必填异常问题
问题复现代码
DependencyCheck.java
package com.yuv.spring.dependencyCheck; import java.util.List; import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class DependencyCheck { @Value("123") private int id; private String name; @Value("#{itemList}") private List<String> itemList; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } @Required public void setId(int id) { this.id = id; } public List<String> getItemList() { return itemList; } public void setItemList(List<String> itemList) { this.itemList = itemList; } @Override public String toString() { return "DependencyCheck [id=" + id + ", name=" + name + ", itemList=" + itemList + "]"; } }
Test.java
package com.yuv.spring.dependencyCheck; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "com/yuv/spring/dependencyCheck/config.xml"); DependencyCheck obj = (DependencyCheck) context.getBean("idRequired"); System.out.println(obj); } }
Config.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" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> <util:list id="itemList" list-class="java.util.ArrayList"> <value>1</value> <value>2</value> </util:list> <context:annotation-config /> <context:component-scan base-package="com.yuv.spring" /> <bean name="idRequired" class="com.yuv.spring.dependencyCheck.DependencyCheck" p:name="yuvraj"> <property name="id" value="123" /> </bean> <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" /> </beans>
问题现象
- 移除
DependencyCheck类setId()方法上的@Required注解时,程序可正常运行,123可成功注入id属性,运行结果符合预期,输出为:
DependencyCheck [id=123, name=yuvraj, itemList=[1, 2]]
- 保留
setId()上的@Required注解时,程序抛出异常:
Property 'id' is required for bean 'dependencyCheck'
已经通过XML配置、@Value注解两种方式为id属性赋值,不清楚异常触发原因。
问题根因
异常信息已经明确标注报错的Bean名称是dependencyCheck,不是手动在XML中配置的idRequired,触发报错的是Spring自动扫描生成的多余Bean:
DependencyCheck类上加了@Component注解,同时开启了包扫描,Spring启动时会自动创建一个名为dependencyCheck(类名首字母小写)的同类型Bean- 这个自动扫描生成的Bean,既没有在XML中显式配置
id属性的注入,写在id字段上的@Value又是字段级注入——直接通过反射修改私有字段值,不会走setId()方法。而@Required的校验逻辑只认setter入口的属性注入、以及Bean定义中显式配置的property,感知不到字段上的直接注入,因此判定必填属性缺失抛出异常。 - 手动配置的
idRequiredBean本身已经显式配置了id属性,完全符合@Required的校验规则,从来不是报错的主体。
排查思路
- 先读全异常信息,不要只看属性缺失的描述,重点确认报错的Bean名称,先定位到出问题的Bean实例
- 梳理容器中同类型Bean的所有来源:检查是否有自动扫描、JavaConfig配置等方式生成的额外Bean,不要只盯着自己手动写的XML配置
- 明确注解的作用边界:
@Required是作用在setter方法上的校验注解,仅校验通过setter完成的依赖注入,不识别直接作用于私有字段的注入逻辑。
解决方案
根据使用场景选一个即可:
- 方案1:如果本来就打算全靠XML手动配置这个类的Bean,直接删掉
DependencyCheck类上的@Component注解,避免Spring重复生成多余的扫描Bean即可解决问题。 - 方案2:如果要保留自动扫描的Bean,把字段上的
@Value("123")移到setId()方法上,让注入走setter入口,@Required的校验就能识别到该属性已经完成注入,不会抛错。 - 方案3:如果要保留
@Component和字段注入的写法,就在包扫描配置里添加排除规则,不让Spring自动注册这个类的Bean:
<context:component-scan base-package="com.yuv.spring"> <context:exclude-filter type="assignable" expression="com.yuv.spring.dependencyCheck.DependencyCheck"/> </context:component-scan>
- 补充提示:
@Required是Spring早期版本的老旧API,目前已经被标记为废弃,后续学习SpringBoot时推荐使用构造器注入配合空值校验,不需要再使用这个注解。
内容的提问来源于stack exchange,提问作者yuvraj singh
相关产品推荐
相关产品推荐

