为什么Spring不支持直接字段依赖注入(除了自动装配)?

13 浏览
0 Comments

为什么Spring不支持直接字段依赖注入(除了自动装配)?

我对直接字段依赖注入很感兴趣。传统上,Spring支持构造函数注入(向构造函数提供参数)和基于setter的注入(在调用时调用setter方法)。\n然而,Spring也支持直接字段注入(在没有setter方法的情况下设置对象的成员字段),这可以通过使用@Autowired注解字段来证明。自动装配仅限于“bean”,因此无法注入原始值(尽管可以通过创建类“java.lang.String”的bean来绕过此问题 - 这可以工作,但具有自动装配的常规注意事项。)此外,Spring还支持@Value,用于直接从属性等设置值到成员字段。\n然而,Spring不允许将属性直接设置为成员字段(不进行自动装配)。\n我的问题是:为什么?\n显然,它有能力这样做,那么为什么它不这样做呢?是否存在任何阻止这样做的重大负面影响?或者这种能力在某种程度上受到限制,只有自动装配才有意义?它是否需要比调用setter方法更大的修改?\n请注意,我不希望讨论是否总体上应该具有setter和getter的优势,只想知道Spring做出这个选择的原因。

0
0 Comments

为什么Spring不支持直接字段依赖注入(除了@Autowired)?

Spring确实通过JSR-250注解(在Spring 3.0+中)支持这一点。

我个人更喜欢这种方式而不是setter注入,并且在考虑构造函数注入时对此有些矛盾。以下是我考虑的一些因素:

1)构造函数注入是一种很好的自述文档化bean依赖关系的方式(利),但是它会产生许多DRY违规:(a)私有字段,(b)构造函数参数,(c)构造函数代码来从参数设置字段,(d)bean配置中的额外代码(无论是在类中还是在xml中)。为了一些封装纯洁性而产生这么多DRY违规,我并不在意。这只是对封装的一种微小违规,但它确实对某些遵守JSR-250注解的注入容器产生了很大的依赖(请参见下一条)。

2)它对JSR-250兼容容器有依赖。对此我有些矛盾。当我第一次听到它时,我认为它会使我的系统更难测试。然而,我最终还是在我的测试中使用了Spring。我仍然可以像往常一样使用模拟bean,所以这从来不是真正的问题。问题是,在测试之外的情况下,你实际上什么时候想要重用它。在我看来,如果你设计系统来利用容器,那就拥抱它并使用它。这些DRY违规真的值得不在容器中运行的灵活性吗?至少通过JSR-250注解,您可以在任何JEE6环境中运行并获得所需的注入。

3)如果在容器之外实例化一个bean,可能会产生一些不太好的调试场景:例如,你将得到空指针异常而不是什么好的提示。这是一种权衡。我个人认为这并不可怕 - 我是说,如果你在一个带有的行上得到一个NPE,你很快就会意识到它没有被注入。

注解是按名称自动装配的,这不是我想要的。

0
0 Comments

为什么Spring不支持直接字段依赖注入(除了@Autowired)?

通过阅读Spring源代码,我自己找到了答案。下面是我发现的内容:

通过XML设置属性可能是Spring最古老的部分,它非常依赖于"java.beans"类进行内省、属性枚举等操作。很明显,这些类根本不支持字段内省。此外,还有类型转换机制,确定属性值如何转换为适合该属性的值。这里没有清晰可分的部分。

所有与等相关的东西都是在BeanPostProcessor中实现的,它有自己的类型匹配机制,与类型转换无关。这也是为什么它只注入bean的原因。对于@Autowired也是一样,它只是在那里解析并与属性无关。

因此,添加字段注入支持,特别是对于属性,不是一个简单的工程工作,因为负责其中一种工作的代码部分与另一种几乎完全独立。

这并不完全回答了“为什么”,但我认为这是一个更有说服力的解释,解释了为什么Spring没有添加直接字段依赖注入,而不是其他我听到的解释。除非他们对此有一些根本性的问题(我怀疑,因为他们想允许配置现有的第三方类,而不仅仅是JavaBeans),否则这只是一项工程努力的问题,以实现这个功能。

0
0 Comments

为什么Spring不支持直接字段依赖注入(除了@Autowired)?

Spring不支持直接字段依赖注入的原因有以下三个方面:

1. 在Spring配置文件中,配置是通过bean属性(getter和setter)完成的。如果存在getter和setter方法,很难确定是调用setValue还是设置成员变量的值。

2. 直接字段依赖注入会破坏封装性。Spring配置没有理由知道私有成员变量。使用注解是可以的,因为它已经在源代码中存在。

3. 安全问题。更严格的安全管理器可能不允许通过反射使私有字段可访问。

针对这些问题的解决方法如下:

1. 对于情况1,可以优先选择使用setter方法,在setter方法不存在的情况下再查找对应的字段。

2. 对于情况2,如果Spring可以调用私有setter方法,那么我不明白为什么同样的访问限制不能应用于成员变量。使用注解也是可以接受的,只是不使用@Autowired注解。

3. 对于情况3,如果更严格的安全管理器不允许通过反射使私有setter方法可访问,那么同样的访问限制也可以应用于成员变量。

私有setter注入也不是一个好主意。封装性是关键,无论是访问私有成员还是方法,都会破坏封装性,违反面向对象编程和依赖注入的原则。安全问题也是相同的。

如果setter方法是public的,为什么成员字段不可以是public的?或者,如果setter方法是private的,设置一个私有成员字段是否有更多的安全隐患?

根据JavaBean规范,类的属性必须通过get、set、is方法进行访问。如果你将成员字段设置为public而没有访问器,那么你就不符合规范,也不是一个JavaBean。如果你想添加额外的检查,但已经在代码中直接访问字段,会发生什么?

这涉及到关于setter/getter的一般优点的讨论。在Spring的情况下,他们明确提到他们支持管理除了严格遵守JavaBean规范的类之外的其他类。此外,如果变量仅通过Spring进行依赖注入设置,那么在添加setter时不需要更改任何代码——Spring会自动检测到并且不需要做任何改动。

我发现遵循标准和面向对象的最佳实践比调整类以适应依赖注入框架更容易。我理解你的观点,并且我认为在Java中使用getter和setter的方式是一种语言限制。

我给出一个Spring应该支持这个功能的原因:还有其他很好的库,它们的配置类都是使用全部公共成员(没有构造函数参数,没有setter或getter)。如果Spring不支持OP描述的功能,那么我必须创建包装器才能使用Spring。也许你不相信这在大型库中是真的,所以我只想指出:api.mongodb.org/java/2.6/com/mongodb/MongoOptions.html

我非常确定对于这种情况,Spring有一个BeanWrapper实现。这个问题更多的是关于如何通过DI容器访问私有字段。

0