Spring框架中有三种注入变量:

  • 基于二传手的注射
  • 基于构造函数的注入
  • 基于现场的注入

这些机制中的每一种都有优点和缺点,并且不仅只有一种正确的方法。 例如现场注入:

@Autowired
private FooBean fooBean;

在生产代码中使用它通常不是最好的主意,主要是因为它使我们的bean无法在不启动Spring上下文或不使用反射hack的情况下进行测试。 另一方面,它几乎不需要其他代码,并且可以在集成测试中使用-绝对不会独立实例化。 在我看来,这是基于现场注射的唯一情况。

现在,让我们关注两个主要变体。 在Spring文档中,我们可以读到

…将构造函数参数用于强制性依赖项并将设置器用于可选的依赖项是一个很好的经验法则。

同样在参考Spring到3.1的文档中 ,我们可以找到一个句子

Spring团队通常提倡setter注入,因为大量的构造函数参数可能变得笨拙,尤其是当属性是可选的时。

这种情况在文档中已更改为第四版,其中指出:

Spring团队通常提倡构造函数注入,因为它使人们能够将应用程序组件实现为不可变对象,并确保所需的依赖项不为null。

尤其是在版本4.0之前的人们使用基于构造函数的注入方式(其中有些“纯粹主义者”(也可以在本文档中找到))时, 这非常酷:)请注意,在第四个框架发布之前,这种注入方式存在很大的问题–方面要求使用默认构造函数。 现在仍然存在基于构造函数的注入的“缺点”:它不允许循环依赖。 我特意在双引号中添加了缺陷,因为对我而言,这是该机制的巨大优势:)文档中还有另外一句话:

通常建议不要在bean之间使用循环引用。

但为什么? 如果我们的应用程序中有循环引用,该怎么办? 我不想写关于应用程序设计的文章,因为几乎总是可以重构我们的代码并将有问题的逻辑委托给第三个bean。 有两个重大而不幸的“沉默”问题。

第一个陷阱

调用ListableBeanFactory.getBeansOfType()方法时,不能确定将返回哪些Bean。 让我们看一下DefaultListableBeanFactory类的代码:

if (isCurrentlyInCreation(bce.getBeanName())) {if (this.logger.isDebugEnabled()) {this.logger.debug("Ignoring match to currently created bean '"+ beanName + "': " + ex.getMessage());}// ...continue;
}

如您所见,如果您不使用DEBUG日志记录级别,那么将有零个信息表明Spring在解析过程中跳过了特定的bean。 如果您想获得所有事件处理程序,那就太麻烦了:)

第二个陷阱

第二个问题涉及AOP。 如果要在bean上使用方面,请确保它不涉及循环引用-否则Spring将创建bean的两个实例–一个没有方面,另一个具有适当方面。 当然仍然没有任何信息。 惊讶吗

对我来说, 停止在我们的应用程序中使用循环依赖就足够了(特别是与此相关的行为可能更有趣)。

请勿使用循环依赖!

但是,我们该如何摆脱困境呢? 当然,您可以使用基于构造函数的注入:)但是,如果您有大量的应用程序,那么花很多时间重写所有类以使用构造函数而不是setter并不是最好的主意。 幸运的是,我有个好消息– AbstractRefreshableApplicationContext类中的allowCircularReferences字段。 只需添加一行到应用程序上下文创建(所描述的方式在这个岗位 )

AnnotationConfigWebApplicationContext applicationContext =new AnnotationConfigWebApplicationContext();
applicationContext.setAllowCircularReferences(false);
// rest of context initialization

最后,为了使您心情愉快,我从DefaultListableBeanFactory粘贴了另一个代码片段:

catch (NoSuchBeanDefinitionException ex) {// Shouldn't happen - probably a result of circular reference resolution...if (logger.isDebugEnabled()) {logger.debug("Failed to check manually registered singleton with name '"+ beanName + "'", ex);}
}

祝你今天愉快! :)

翻译自: https://www.javacodegeeks.com/2015/01/dependency-injection-pitfalls-in-spring.html

Spring的依赖注入陷阱相关推荐

  1. factorybean 代理类不能按照类型注入_《Spring入门经典》:使用Spring进行依赖注入

    第二章:使用Spring进行依赖注入 重点:配置并使用Spring容器 使用不同类型的配置元数据来配置Spring容器 理解依赖解析 了解自动装配的优缺点 在容器中执行显式Bean查找 学习不同的Be ...

  2. 在ABAP里模拟实现Java Spring的依赖注入

    Dependency Injection- 依赖注入,在Java Spring框架中有着广泛地应用.通过依赖注入,我们不必在应用代码里繁琐地初始化依赖的资源,非常方便. 那么ABAP能否从语言层面上也 ...

  3. Spring Setter依赖注入示例

    学习如何编写Spring Setter依赖注入示例 . Setter注入是Spring依赖注入的一种 . Spring支持字段注入,Setter注入以及构造函数注入,以将依赖项注入Spring托管的b ...

  4. Spring字段依赖注入示例

    学习如何编写Spring Field Injection示例 . 字段注入是Spring框架 依赖注入的一种 . 在本教程中,我们将编写几个类,并看一看现场注入工程. 有关Spring依赖注入的更多信 ...

  5. 据说,80%的人没有真正理解了Spring的依赖注入

    前言 提起Spring,大家肯定不陌生,它是每一个Java开发者绕不过去的坎.Spring 框架为基于 java 的企业应用程序提供了一整套解决方案,方便开发人员在框架基础快速进行业务开发. 在官网中 ...

  6. Spring框架----Spring的依赖注入

    1.spring的依赖注入的概念 依赖注入:dependency Injection IOC的作用:降低程序之间的依赖关系,但不是消除. 依赖关系的管理:以后都交给了spring来维护 在当前类中需要 ...

  7. Spring和依赖注入的价值

    javaeye上看到有帖子,置疑spring和依赖注入的价值,回复内容整理如下: 依赖注入对设计有利,而spring则促进了依赖注入的使用. 如果业务处理类,它所使用的倚赖,都是依靠在这个类内部实现或 ...

  8. spring(一)依赖注入与 SPEL

    Spring之依赖注入与 SPEL 一.控制反转与依赖注入 二.helloworld 三.构造注入 四.级联注入 五.单例与多例 六.工厂方法创建 Bean 七.包扫描管理 bean 八.SPEL与资 ...

  9. Spring实现依赖注入的几种方式

    Spring实现依赖注入的几种方式 1.基于有参构造实现 <bean id="user" class="com.ccu.twj"><const ...

最新文章

  1. AI识别彻底懵逼,这到底是“牛”还是“鲨”?
  2. 养成良好的学习习惯-浅谈学习方法(1)
  3. Android向上显示更多内容,如何在Android中为2个父项实现向上导航,指向1个子活动...
  4. Hive用户权限管理理解
  5. 【Python】Python+Matplotlib+LaTeX玩转数学公式
  6. Boost:boost :: bind相等运算符的测试程序
  7. 二值图片连续区域检测
  8. 直播P2P技术2-低延迟模型
  9. python定义初始化函数_Python 语言定义的Class的初始化函数的函数名是( )
  10. Win10环境下使用VS2015编译PJProject
  11. 2013.05.09
  12. SSD目标检测论文简读
  13. 手动杀毒,SOLA病毒(也称之为worm.script.bat.Agent、Trojan.Win32.Sola病毒)
  14. 解决Windows系统删除文件:文件正在使用,无法删除问题
  15. 有限差分法求解高阶导数
  16. 云大计算机初试最高分,【经验谈】初试总分360+,专业排名前五!云大社会工作专......
  17. 我沪漂 16 年,再也不打工了!
  18. Android P 适配
  19. 计算机控制电缆芯数,控制电缆芯数详细解读
  20. while和do—while循环语句

热门文章

  1. Truebine聚合监控
  2. 字段缺失_区分Protobuf 3中缺失值和默认值
  3. import javax.servlet.ServletRequest 关于IDEA javax.servlet.http.HttpServletRequest 不存在 解决方案
  4. centos Error: Cannot find a valid baseurl for repo: base 解决方法
  5. 如何查阅相关工作所用到的文献资料
  6. 反射和配置文件的实际应用
  7. java观察者设计模式_Java中的观察者设计模式
  8. starter_您是否尝试过MicroProfile Starter?
  9. jakarta ee_适用于Java EE / Jakarta EE开发人员的Micronaut
  10. spring boot示例_Spring Boot完成示例