在阅读 Spring 源码时,你可能会注意到在 AbstractAutowireCapableBeanFactory
的构造方法中,有这样一段代码:
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
这些接口被加入到了一个叫 ignoredDependencyInterfaces
的容器中。那么,这个容器到底有什么用?为什么要忽略这些接口?本文带你一探究竟。
1. 什么是 ignoredDependencyInterfaces?
ignoredDependencyInterfaces
是一个 Set<Class<?>>
类型的集合,用来存放在自动装配(autowiring)和依赖检查(dependency check)时需要"跳过"的接口。
简单来说:
凡是放进这个集合的接口,Spring 在自动注入依赖时会自动忽略,不会尝试为它们注入 Bean。
2. 为什么要忽略这些接口?
Spring 中有一类特殊的接口,叫做 “Aware” 接口,比如:
BeanFactoryAware
ApplicationContextAware
BeanNameAware
BeanClassLoaderAware
实现这些接口的 Bean,会由 Spring 容器通过特殊的回调方式自动注入相关依赖,而不是通过常规的自动装配。
举个例子:
如果你的 Bean 实现了 BeanFactoryAware
,Spring 会自动调用 setBeanFactory()
方法,把 BeanFactory 传给你。
这时,如果 Spring 还试图通过自动装配为 BeanFactory
这个属性注入依赖,就会重复甚至出错。
3. 工作机制简述
Spring 在自动装配时,会判断某个属性是否需要被注入。判断的逻辑大致如下:
protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
}
只要属性的 setter 方法定义在 ignoredDependencyInterfaces
里的接口上,Spring 就会跳过对它的自动注入。
4. 实际应用场景
- BeanFactory 通过实现
BeanFactoryAware
接口注入 - ApplicationContext 通过实现
ApplicationContextAware
接口注入
这些依赖都不是通过 @Autowired
或构造器注入的,而是 Spring 容器在 Bean 初始化时自动回调注入。
5. 如何自定义忽略的接口?
如果你有自定义的 Aware 接口,也可以通过如下方法让 Spring 忽略它:
public void ignoreDependencyInterface(Class<?> ifc) {
this.ignoredDependencyInterfaces.add(ifc);
}
只需调用 ignoreDependencyInterface(YourAwareInterface.class)
即可。
6. 总结
ignoredDependencyInterfaces
让 Spring 在自动装配时跳过某些特殊接口,避免重复或错误注入。- 主要用于各种 Aware 回调接口,这些接口的依赖由 Spring 容器以特殊方式注入。
- 你可以自定义需要忽略的接口,保证依赖注入的灵活性和正确性。
一句话总结:
ignoredDependencyInterfaces 是 Spring 自动装配机制中的"白名单",专门用来避免对 Aware 等特殊接口的重复注入,让依赖注入更安全、更智能!
如果你还有疑问,欢迎留言讨论!