【问题标题】:Injecting beans into a class outside the Spring managed context将 bean 注入到 Spring 托管上下文之外的类中
【发布时间】:2010-09-23 12:59:50
【问题描述】:

我是我公司的一种产品的最终用户。它不太适合集成到 Spring 中,但是我能够处理上下文并按名称检索所需的 bean。但是,我仍然想知道是否可以将 bean 注入到这个类中,即使这个类不是由 Spring 本身管理的。

澄清:管理某个类 MyClass 的生命周期的同一个应用程序也在管理 Spring 上下文的生命周期。 Spring对MyClass的实例一无所知,我想知道如何将实例提供给上下文,但无法在上下文本身中创建实例。

【问题讨论】:

  • 请澄清:您想通过 Spring Configuration、在运行时动态注入 Spring 或通过 setter 以编程方式注入 bean?
  • 任何方法都可以。关键是应用程序已经创建了我要注入 bean 的对象,因此原始对象不受 Spring 上下文管理。
  • 另外,考虑使用工厂方法,以便您可以将类放入应用程序上下文并按照普通 Spring bean 进行配置。查看有关 bean 工厂的 Spring 参考文档。
  • 我不确定工厂方法如何再访问不受 Spring 上下文管理的 bean,这是问题的重点。

标签: java spring


【解决方案1】:

你可以这样做:

ApplicationContext ctx = ...
YourClass someBeanNotCreatedBySpring = ...
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(
    someBeanNotCreatedBySpring,
    AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, true);

您可以在YourClass中使用@Autowired等指定要注入的字段等。

【讨论】:

  • 我从来没有机会尝试这个,但它似乎与我所寻找的最接近。试一试就好了。
  • 这个answer 解释了如何获得ApplicationContext
【解决方案2】:

尽管制造是外部的,但将 bean 引入 Spring 的一种方法是使用标记为 @Configuration bean 的辅助类,该类具有一个方法(标记为 @Bean),该方法实际上生成实例并将其交还给Spring(此时会进行属性注入和代理生成)。

我不太确定您需要什么范围;使用prototype,您将在每个地方获得新鲜的豆子。

@Configuration
public class FooBarMaker {
    @Bean(autowire = Autowire.BY_TYPE)
    @Scope("prototype")
    public FooBar makeAFooBar() {
        // You probably need to do some more work in here, I imagine
        return new FooBar();
    }
}

您可以将制造所需的属性注入@Configuration bean。 (我使用它来创建接口的实例,其中要实例化的类的名称是在运行时定义的。)

【讨论】:

    【解决方案3】:

    假设你有以下依赖链:

    A --> B --> C --> x --> y --> Z

    A、B、C是spring管理的bean(由spring框架构建和管理) x, y 是由您的应用程序构建的非常简单的 POJO,无需 spring 辅助

    现在,如果您希望 y 使用 spring 获得对 Z 的引用,您需要对 spring ApplicationContext 有一个“句柄”

    一种方法是实现ApplicationContextAware interface。在这种情况下,我建议 A、B 或 C 实现此接口并将 applicationContext 引用存储在静态成员中。

    我们以 C 类为例:

    class C implmenets ApplicationContextAware{
        public static ApplicationContex ac;
         void setApplicationContext(ApplicationContext applicationContext)  {
                   ac = applicationContext;
         }
     .............
    }
    

    现在,在 y 类中,你应该有:

    (Z)(C.ac.getBean("classZ")).doSomething()
    

    HTH -- Yonatan

    【讨论】:

    • 怎么样:x 和 y 不依赖于 C,我希望将 Z 注入到 x 或 y 中?看来我必须在spring-context中使用@Comparable标签,然后在事后进行一些运行时编织。到目前为止,我还没有设法让这个工作,并增加了额外的工作。寻找更简单的方法。
    • 您正在从非静态的“setApplicationContext”方法设置“ac”(静态)。理想情况下,静态字段仅从同步的静态方法中更新。否则,如果有多个类实例和/或多个线程在运行,这很容易导致错误。
    【解决方案4】:

    另一种方法是使用 AspectJ。这是将 Spring bean 注入使用 new 运算符创建的非托管对象的推荐方法。有关详细信息,请参阅此:

    http://www.javacodegeeks.com/2011/02/domain-driven-design-spring-aspectj.html

    【讨论】:

    • 不,这不是最好的方法。 POV 来自 DDD 模型,而不是 OOP:v
    【解决方案5】:

    搜索无尽的 autowire injection spring bean into pojo applicationcontextaware beanaware 等组合让我回到了这里,但这并没有为我提供足够完整的解决方案。

    这是这个 IMO 的一个更好的实现/教程: 我希望它可以帮助每个喜欢它的人最终帮助我。

    Accessing Spring Beans from outside Spring Context

    【讨论】:

      【解决方案6】:

      请注意,在最旧版本的 Spring 中,bean factory http://jira.springframework.org/browse/SPR-4672 存在线程安全问题

      【讨论】:

        【解决方案7】:

        如果您想在 Spring 上下文之外创建一个对象,并使该对象可用于注入到其他 在 Spring 上下文中的 bean,您可以按照进入this article

        基本上,您创建一个父应用程序上下文并将您的外部对象作为单例推送到该父上下文中。然后创建主应用程序上下文(例如,从 xml 文件),以父应用程序上下文作为其父项。

        Object externalObject = ...
        GenericApplicationContext parent = new StaticApplicationContext();
        parent.getBeanFactory().registerSingleton( "externalObject", externalObject );
        parent.refresh();
        ApplicationContext appContext = new ClassPathXmlApplicationContext( ... , parent);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-19
          • 1970-01-01
          • 2013-01-23
          • 2014-07-01
          • 1970-01-01
          相关资源
          最近更新 更多