gpt4 book ai didi

java - 如何做 iPOJO 实例化

转载 作者:行者123 更新时间:2023-11-30 08:24:37 25 4
gpt4 key购买 nike

我在理解 iPOJO 中组件实例化的概念时遇到了一些问题。我读了 this guide
我得到了类和对象的类比,但我仍然有一些具体的问题和一些概念上的问题,我希望有人能澄清

我以为我需要通过 iPOJO(@Instantiate 或工厂)创建实例 只有对于服务提供商,因为他们从不使用 new,因为 impl 总是隐藏的。但是,我有一些我自己实例化的消费者@Component(比如在 main() 方法中,我直接对它们调用 new )。我让他们 @Component 因为他们需要注入(inject)东西。我假设 ipojo 字节码操作会使其在构造对象时注入(inject)它们的依赖项(我主要使用 @Bind 的方法注入(inject)),但似乎并非如此。有人可以向我澄清这一点吗?现在在我看来,对于 iPOJO 进行任何注入(inject),我都需要始终使用 iPOJO 实例化技术之一。我遇到的问题是,我在消费者类中创建的构造函数没有被调用。

这是一个简单的例子来说明我的困惑

@Component(name="test")
public class MyFoo {
private List<External> externals; //injected
private Bar bar; //passed via constructor. Bar is *not* a @Component

public MyFoo(Bar otherBar) {
bar = otherBar;
externals = new ArrayList();
}

@Bind(aggregate=true)
public addExternal(External service) {
externals.add(service);
}
}

所以,从这里可以看出,我需要拥有接口(interface) External 的所有提供者。 ,但我还需要一个 Bar使用 new MyFoo(someBar) 构造对象时传递的对象

我的问题是,如果我需要通过 Bar到构造函数然后我需要使用 new;但是如果我使用 new,iPojo 永远不会调用我的注入(inject)方法。另一方面,如果我使用 iPOJO 实例化(比如我添加了 @Instantiate),那么注入(inject)确实发生了,但构造函数没有被调用,所以绑定(bind)会抛出一个 NPE,因为列表还没有被创建 + bar 将不会被设置。我知道我可以在 bind 方法中创建列表,但我的问题更具概念性。
  • 你应该如何完成这个(框架注入(inject)+构造函数中的参数传递)?
  • iPOJO 如何在不调用我的唯一一个创建对象的构造函数的情况下调用 addExternal(这意味着对象已创建)?这在标准 java
  • 中非常违反直觉
  • 在使用 iPOJO 组件时,您是否不应该使用构造函数?
  • 最佳答案

    iPojo 的工作方式类似于其他 DI(依赖注入(inject))框架,例如 Blueprint (OSGi)、Spring、Guice 等。也就是说,为了让 DI 完成它的工作,您必须让容器 (iPojo) 管理您正在与之交互的对象。所以,您的倾向是正确的:您必须使用 iPojo 的一种实例化技术。如果您选择在对象上使用 new,则您的代码将管理生命周期(因此您将需要手动“注入(inject)”所有参数)。

    在示例中,您的构造函数没有被调用,因为开箱即用的 iPojo 将支持两种主要情况:默认构造函数 (MyFoo()) 或接受 BundleContext 的构造函数 (MyFoo(BundleContext c))。如果您使用的是 1.7.0 或更高版本,iPojo 还支持构造函数服务和属性注入(inject) @Requires/@Property分别在您的构造函数变量(或元数据中的等价物)上。

    当iPojo bytecode manipulation开始,它操纵字节码使其可由 iPojo 管理,而不是由 iPojo 管理。它通过添加一个 MyClass(InstanceManager) 构造函数以及 iPojo 在实例化您的对象时在内部使用的其他东西来实现这一点。

    所以,回答你的问题:

  • 您可以通过将注入(inject)的变量定义为属性或服务需求并委托(delegate) iPojo 来创建它们来实现这一点。 iPojo 有 multiple methods用于与实例创建交互,但您可能感兴趣的两个是通过 OSGi ConfigurationAdmin 或 iPojo 工厂(假设 publicFactory 在您的 @Component 上设置为 true ,这是默认值)。作为使用配置管理员的示例,并假设 Bar 不在 OSGi 服务注册表中,您的 MyFoo 类将如下所示:
    @Component(name="test")
    public class MyFoo {
    private List<External> externals; //injected
    private Bar bar; //passed via constructor. Bar is *not* a @Component

    public MyFoo(@Property(name = "somebar") Bar otherBar) {
    bar = otherBar;
    externals = new ArrayList();
    }

    @Bind(aggregate=true)
    public addExternal(External service) {
    externals.add(service);
    }
    }

    然后,您将使用配置管理员(或 iPojo 工厂)来创建一个实例。因此,您的主要方法将从 OSGi 服务层中拉入 ConfigAdmin 或 iPojo 工厂(例如,通过从 BundleContext 中拉出它,等等),创建一个将“somebar”属性设置为“new Bar()”的配置"并保存该配置。然后,为您创建的 iPojo 托管服务工厂将使用您在配置中提供的新 Bar 实例化 MyFoo 的一个版本,并将其注入(inject)到 MyFoo 构造函数中:
    ...
    Configuration config = configAdmin.createFactoryConfiguration(
    MyFoo.class.getCanonicalName());
    Hashtable<String, String> properties = new Hashtable<>();
    properties.put("somebar", new Bar()); // This is where you new
    config.update(properties);
    // do something useful with the config if you need to update
    // the instance or destroy it later.
    ...

    配置管理员的第一个参数 createFactoryConfiguration指定pid。在这种情况下,pid 是类的名称,这是 iPojo 将默认使用的名称,除非您在 @Component 中覆盖它。注解。然后将 somebar 添加到属性并更新配置。 iPojo 工厂与此类似,但我相信它使用构建器模式来创建实例。如果您不想添加对 OSGi 配置管理员的依赖,最好使用 iPojo 工厂。
  • 我不是 iPojo 内部的专家,我在这里根据我的经历和我在他们的文档中读到的内容得出结论。如前所述,iPojo 执行字节码操作来扩充您的类,使其可由 iPojo 管理。它添加到您的类中的一个特征是带有 InstanceManager 的构造函数。 .由于您添加的构造函数没有绑定(bind)元数据(即注释——我假设 list 或 xml 文件中没有手动元数据)它或多或少完全忽略了该构造函数,而是选择使用那个由字节码操作过程动态生成。完成后,它最终会调用您的 @Bind添加外部服务的方法(因为该方法已标记),您将发现自己处于您描述的状态。
  • 这里的关键是让 iPojo 管理您的对象的生命周期,如上所述。通过调用构造函数,您实际上是在管理该实例的生命周期,因此 iPojo 不在循环中。因此,您可以使用构造函数并手动将参数“注入(inject)”其中,也可以依靠 iPojo 为您执行此操作。
  • 关于java - 如何做 iPOJO 实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22847701/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com