Spring中@Autowired与@Required在setter注入中的差异及相关疑问
嘿,我来帮你把@Autowired和@Required在setter注入里的差异讲透,这俩注解乍一看功能有点重叠,但本质完全不一样,我之前踩过坑,给你拆解清楚:
1. 默认@Autowired(未加required=false)和@Required作用相同吗?
完全不同!核心区别在于一个是主动注入,一个是被动检查:
@Autowired(required=true)(默认):是Spring的依赖注入注解,它会主动从容器中查找匹配的Bean,通过这个setter方法注入进去。如果找不到匹配的Bean,直接抛出异常——它的核心是“我要通过Autowired机制拿到这个依赖”。@Required:它是一个标记性注解,本身不负责注入任何东西,只是告诉Spring:“这个属性必须被设置(不管用什么方式)”。不管你是通过XML的<property>配置、@Autowired注入,甚至是手动调用setter方法,只要最终这个属性不为null就行。如果属性没被设置,Spring才会报错——它的核心是“这个属性不能是空的,至于怎么来的我不管”。
举个例子:如果你的类用了@Required标记setter,但你是通过XML配置<property>来赋值的,完全不需要@Autowired,Spring照样会检查属性是否被填充;但如果用@Autowired的setter,Spring只会用Autowired的逻辑去注入,哪怕你XML里配置了<property>,那是额外的赋值,不是@Autowired的职责。
2. @Required能额外获得哪些特性?
主要是注入方式的灵活性和语义的纯粹性:
- 不绑定注入方式:它不限制依赖的来源,支持XML配置、注解注入、手动赋值等所有能设置属性的方式,是一种“声明式约束”,只关心结果(属性非空),不关心过程。
- 语义更清晰:它明确表达“这个属性是Bean正常工作的必要条件”,而不是“必须用Autowired来注入这个属性”。其他开发者一看就知道,这个属性必须有值,但可以用任何方式设置。
- 兼容旧的XML配置:在Spring早期以XML配置为主的时代,
@Required是用来配合XML配置做非空检查的,现在虽然注解流行,但它依然能兼容混合配置场景。
3. 为什么setter注入场景更推荐@Required而非@Autowired?
这和setter注入的设计初衷有关:setter注入本来就是为了灵活修改属性(比如后续通过XML调整、或者在运行时手动修改),而@Required完美契合这个场景:
- 保留灵活性:如果用
@Autowired标记setter,相当于把这个setter和Autowired注入机制绑定死了。后续如果想改成XML配置注入,你得删掉@Autowired注解;但用@Required的话,只要在XML里配置<property>就行,代码完全不用改。 - 语义更匹配:setter注入的核心是“设置属性”,而
@Required只是声明“这个属性必须被设置”,刚好对应;@Autowired的核心是“自动注入”,和setter的“设置”语义不完全一致。 - 避免过度绑定:
@Autowired会让setter方法只能用于Autowired注入,而@Required允许setter方法被任何方式调用,同时保证属性非空。
代码示例对比
用@Required的setter注入(兼容XML配置)
public class MyService { private UserRepository userRepo; // 标记这个属性必须被设置,不管用什么方式 @Required public void setUserRepo(UserRepository userRepo) { this.userRepo = userRepo; } public void doSomething() { userRepo.findById(1L); // 放心用,Spring保证userRepo非空 } }
对应的XML配置(不需要任何注解注入):
<bean id="myService" class="com.example.MyService"> <property name="userRepo" ref="userRepository"/> </bean> <bean id="userRepository" class="com.example.JdbcUserRepository"/>
用@Autowired的setter注入(绑定Autowired机制)
public class MyService { private UserRepository userRepo; // 告诉Spring必须通过Autowired注入这个依赖 @Autowired public void setUserRepo(UserRepository userRepo) { this.userRepo = userRepo; } public void doSomething() { userRepo.findById(1L); } }
这个时候Spring会自动从容器找UserRepository类型的Bean注入,不需要XML配置,但如果后续想改成XML配置,你得把@Autowired删掉,否则Spring会先做Autowired注入,再执行XML的<property>赋值(可能覆盖),逻辑就乱了。
补充:Spring 5.1之后
@Required已经被弃用了,官方推荐用构造器注入+final字段来保证依赖非空(构造器注入天然保证依赖在Bean初始化时就被设置)。但如果一定要用setter注入,以上的差异依然成立。
内容的提问来源于stack exchange,提问作者Atul
相关产品推荐
相关产品推荐

