控制域对象构造问题的反演

发布于 2024-08-13 22:32:36 字数 667 浏览 3 评论 0原文

据我了解,IoC 容器有助于创建应用程序级对象,例如服务和工厂。但域级对象应该手动创建。 Spring的手册告诉我们:“通常不会在容器中配置细粒度的域对象,因为创建/加载域对象通常是DAO和业务逻辑的责任。”

出色地。但是,如果我的域“细粒度”对象依赖于某些应用程序级对象怎么办? 例如我有一个 UserViewer(User user, UserConstantsconstants) 类。 user 是无法注入的域对象,但 UserViewer 还需要 UserConstants,它是由 IoC 容器注入的高级对象。

我想从 IoC 容器注入 UserConstants,但我还需要一个瞬态运行时参数 User 。

设计有什么问题吗?

提前致谢!

更新

看来我的问题不够精确。我真正需要的是一个如何执行此操作的示例:

创建类 UserViewer(User user, UserService service) 的实例,其中 user 作为参数传递,服务是从 IoC 注入的。

如果我注入UserViewer查看器,那么如何将用户传递给它?

如果我手动创建UserViewer查看器,那么如何将服务传递给它?

As I understand IoC-container is helpful in creation of application-level objects like services and factories. But domain-level objects should be created manually.
Spring's manual tells us: "Typically one does not configure fine-grained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create/load domain objects."

Well. But what if my domain "fine-grained" object depends on some application-level object.
For example I have an UserViewer(User user, UserConstants constants) class.
There user is domain object which cannot be injected, but UserViewer also needs UserConstants which is high-level object injected by IoC-container.

I want to inject UserConstants from the IoC-container, but I also need a transient runtime parameter User here.

What is wrong with the design?

Thanks in advance!

UPDATE

It seems I was not precise enough with my question. What I really need is an example how to do this:

create instance of class UserViewer(User user, UserService service), where user is passed as the parameter and service is injected from IoC.

If I inject UserViewer viewer then how do I pass user to it?

If I create UserViewer viewer manually then how do I pass service to it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

年华零落成诗 2024-08-20 22:32:36

这个设计没有什么问题。为此,您可以使用工厂,它的一侧在域中,一侧在基础设施中。

您可以手动编写它们,也可以让容器为您执行此操作,例如 温莎的 TypedFactoryFacility

此外,当您的域对象来自持久层时,您可以将容器插入其中以注入它们所需的服务(NHibernate 可以做到这一点)。

there's nothing wrong with this design. you use Factories for that, which have one leg in the domain, one leg in infrastructure.

You can either write them manually, or have the container do that for you, by things like TypedFactoryFacility in Windsor.

Also when your domain objects come from persistence layer you can plug your container there to inject the services they require (NHibernate can do that).

兰花执着 2024-08-20 22:32:36

但是如果我的域“细粒度”对象依赖于某些应用程序级对象怎么办?

正是这一点被认为是不好的做法。我想说问题可能是:

  1. 这些对象有大量,因此可能存在性能和内存问题。
  2. POJO风格是它们可以在所有环境中使用(持久化在数据库中,在业务算法和规则中处理,在视图技术中读取和设置,序列化并通过网络发送)。在其中注入应用程序级对象可能会导致以下问题:

    1. 在您的架构中,您可能有这样的规则:某些(大多数)应用程序级对象在某些层中可用,而在其他层中则不可用。因为所有层都可以访问 pojo,所以会传递性地违反该规则。
    2. 当在另一个 JVM 中序列化和重建时,应用程序级对象的含义是什么。它们没有用,必须将它们更改为本地等效项...

通常,构成您的域的 pojo 是独立的。他们可以访问其他 pojo(以及许多枚举),仅此而已。

除了数据之外,它们还具有实现业务规则或算法细节的方法记住对数据和处理数据的代码进行分组的面向对象思想;-) ):

  • 当它们具有继承时,这尤其好,因为这允许通过提供不同的实现来为某些 pojo 自定义业务规则(没有 if 或 switch 的不同情况:还记得 OO 吗?;-))。
  • 任何需要访问应用程序级对象(例如访问数据库)的代码都会被删除,例如服务或管理器。但该代码保持高级别,因此可读且简单,因为 pojo 本身负责低级别细节(以及特殊情况)。

    <块引用>

    事后,您经常会发现 pojo 方法被大量重用,并且由服务或管理器以不同的方式组合。这是减少重复的一大胜利,方法名称提供了急需的“含义”,并为刚接触模块的开发人员提供了更轻松的访问。

But what if my domain "fine-grained" object depends on some application-level object?

It is precisely this that is considered bad-practice. I would say the problems could be:

  1. There are tons of these objects, so there can be performance and memory issues.
  2. The POJO style is that they can be used in all environments (persisted in the database, processed in business algorithms and rules, read and set in view technologies, serialized and send over the network). Injecting application-level objects in them could cause the following problems:

    1. In your architecture, you probably have the rule that some (most) application-level objects are usable in some layers, not in others. Because all layers have access to the pojos, the rule would be violated transitively.
    2. When serialized and rebuild in another JVM, what would be the meaning of your application-level objects. They are useless, they must be changed for the local equivalents...

Typically, the pojos that constitute your domain are self-contained. They can have access to other pojos (and many enums), that's all.

In addition to the data, they have methods that implement the details of the business rules or algorithms (remember the OO idea of grouping data and code that work on it ;-) ):

  • This is especially good when they have inheritance, as this allow to customize a business rule for some pojo by providing a different implementation (differing case without if or switch: remember OO? ;-) ).
  • Any code that requires access to application-level objects (like accessing the database) is taken out, for example to a Service or Manager. But that code stays high level, thus readable and simple, because the pojos themselves take care of the low level details (and the special cases).

    After the fact, you often find out that the pojo methods get reused a lot, and composed in different ways by the Services or Managers. That's a big win on reducing duplication, the methods names provide much needed "meaning", and provide an easier access to developers that are new to a module.

紫﹏色ふ单纯 2024-08-20 22:32:36

对于您的更新:

创建类UserViewer(User user, UserService service)的实例,其中user作为参数传递,service从IoC注入。

如果我注入 UserViewer 查看器,那么如何将用户传递给它?

如果我手动创建 UserViewer 查看器,那么如何将服务传递给它?

在这种情况下,您需要一个工厂方法(可能在您的工厂或定位器上)。它可以如下所示,将两部分分开:

public UserViewer createUserViewer(User user) {
   UserViewer viewer = instantiateBean(UserViewer.class); 
   viewer.setUser(user);
   return viewer;
}

private <E> E instantiateBean(Class<E> clazz) {
   // call the IoC container to create and inject a bean
}

For your update:

create instance of class UserViewer(User user, UserService service), where user is passed as the parameter and service is injected from IoC.

If I inject UserViewer viewer then how do I pass user to it?

If I create UserViewer viewer manually then how do I pass service to it?

In that case, you need a factory method (possibly on a Factory or Locator of yours). It could look at follow, separating the two parts:

public UserViewer createUserViewer(User user) {
   UserViewer viewer = instantiateBean(UserViewer.class); 
   viewer.setUser(user);
   return viewer;
}

private <E> E instantiateBean(Class<E> clazz) {
   // call the IoC container to create and inject a bean
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文