有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java通过依赖注入访问Springbean*而不是*

我们有一些域对象是在运行时创建的,而不是由Spring创建的。这些域对象需要访问由Spring管理的某些服务类型bean。运行时创建的域对象如何动态地(而不是通过DI)访问Springbean


共 (6) 个答案

  1. # 1 楼答案

    Spring有一种称为SingletonBeanFactoryLocator的机制,您可以在EJB2.0应用程序等地方使用该机制,在无法使用依赖项注入的地方获取bean工厂/应用程序上下文。现有Spring ContextLoader中有一个钩子,您已经在使用它来利用这个功能,尽管设置起来有些棘手

    您需要将应用程序上下文分离为父/子关系。父对象将包含服务层对象,而子对象由特定于web层的内容组成

    然后,您必须向web添加几个上下文参数。xml(就像您对配置位置所做的那样)来告诉它初始化父对象:

    <context-param>
        <param-name>locatorFactorySelector</param-name>
        <param-value>classpath:beanRefFactory.xml</param-value>
    </context-param>
    
    <context-param>
        <param-name>parentContextKey</param-name>
        <param-value>beanRefFactory</param-value>
    </context-param>
    

    locatorFactorySelector是对xml文件的引用,但是(这是我经常感到困惑的地方),它不会指向定义服务的xml。它是创建应用程序上下文bean的bean定义xml。然后使用parentContextKey属性引用这个bean

    例如,BeanRefactory。然后,xml将包含:

    <beans>
        <bean id="beanRefFactory"
             class="org.springframework.context.support.ClassPathXmlApplicationContext">
            <constructor-arg>
               <list>
                    <value>service-context.xml</value>
               </list>
            </constructor-arg>
        </bean>
    </beans>
    

    在非死亡域对象中,您可以使用以下代码访问应用程序上下文:

       BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
       BeanFactoryReference contextRef= locator.useBeanFactory(parentContextKey);
       ApplicatonContext context = (ApplicationContext) contextRef.getFactory();
    

    您可以在this blog post中找到有关ContextSingletonBeanFactoryLocator的更多信息。在Java Development with the Spring Framework中关于EJB的章节中,也有关于使用这种方法的详细描述

  2. # 2 楼答案

    创建工厂并向spring注册,使用工厂创建域对象,而不是使用“新建”

    在这种情况下,您的DomainObjFactory拥有所有可用的商品

  3. # 3 楼答案

    @duffymo的答案是这个问题最常见的解决方案,也是你应该遵循的解决方案

    然而,如果你感觉很粗鲁,如果你的情况支持它,那么你可以考虑用Spring的AspectJ支持来支持{a1}春豆:

    [...] contains an annotation-driven aspect that exploits this capability to allow dependency injection of any object. The support is intended to be used for objects created outside of the control of any container. Domain objects often fall into this category because they are often created programmatically using the new operator, or by an ORM tool as a result of a database query.

    它接近伏都教,这种东西,它只在某些应用服务器上工作,但它可能是你的工具

  4. # 4 楼答案

    略相关question

    您可以采用与Hibernate类似的策略,在域实例工厂中为拦截器创建工具。您可以将所需的服务注入到spring管理的拦截器中,拦截器被注入到您的域工厂中

    这将使您的应用程序与特定于Spring的接口分离。下面的例子可以用泛型来简化,但你应该明白这一点

    public interface Interceptor {
      public void onCreate(Object entity);
    }
    
    public class DomainFactory {
      public void setInterceptors(List<Interceptor> interceptors) { ... }
      public Object createInstance() {
        // iterate interceptors, call onCreate
      }
    }
    
    public interface MyServiceAware {
      public void setMyService(MyService service);
    }
    
    public class MyServiceInjector implements Interceptor {
      private MyService myService;
      public void onCreate(Object entity) {
        if (entity instanceof MyServiceAware)
          ((MyServiceAware) entity).setMyService(myService);
      }
    }
    

    然后将其配置为

    <bean id="myServiceInjector" class="MyServiceInjector">
      <property name="myService" ref="someServiceBean" />
    </bean>
    
    <bean class="DomainFactory">
      <property name="interceptors">
        <list>
          <ref bean="myServiceInjector"/>
        </list>
      </property>
    </bean>
    
  5. # 5 楼答案

    您可以使用@duffymo建议的方法,但是如果您不是以web应用程序的形式运行Spring,那么您应该看看这个。请注意,在最流行的答案中,实用程序类是线程安全的。顺便说一句,OP和答案应该是您所需要的,然后您可以使用这个实用程序类来获取对Spring托管bean的引用

  6. # 6 楼答案

    您必须给他们一个对ApplicationContext或BeanFactory的引用,这样他们才能获得Spring管理的bean