Java 通过依赖注入访问Springbean*而不是*
我们有一些域对象是在运行时创建的,而不是由Spring创建的。这些域对象需要访问由Spring管理的某些服务类型bean。在运行时创建的域对象如何动态地(而不是通过DI)访问Springbean?您必须给他们一个对ApplicationContext或BeanFactory的引用,这样他们才能获得Spring管理的bean。您可以使用@duffymo建议的方法,但如果您不是以web应用程序的形式运行Spring,那么您应该这样考虑。请注意,在最流行的答案中,实用程序类是线程安全的。顺便说一句,OP和答案应该是您所需要的,然后您可以使用这个实用程序类来获取对Spring托管bean的引用。@duffymo的答案是这个问题最常见的解决方案,您可能应该遵循这个解决方案 然而,如果你感觉很粗鲁,如果你的处境支持它,那么你可以考虑用Spring的AspectJ支持来支持春豆: […]包含注释驱动的 利用此功能的方面 允许任何 对象该支持旨在: 用于在外部创建的对象 对任何容器的控制。领域 对象通常属于这一类 因为它们经常被创造出来 以编程方式使用新的 运算符,或通过ORM工具作为 数据库查询的结果Java 通过依赖注入访问Springbean*而不是*,java,spring,dependency-injection,Java,Spring,Dependency Injection,我们有一些域对象是在运行时创建的,而不是由Spring创建的。这些域对象需要访问由Spring管理的某些服务类型bean。在运行时创建的域对象如何动态地(而不是通过DI)访问Springbean?您必须给他们一个对ApplicationContext或BeanFactory的引用,这样他们才能获得Spring管理的bean。您可以使用@duffymo建议的方法,但如果您不是以web应用程序的形式运行Spring,那么您应该这样考虑。请注意,在最流行的答案中,实用程序类是线程安全的。顺便说一句,O
它接近伏都教,这种东西,它只在某些应用服务器上工作,但它可能是您的工具。Spring有一种称为
SingletonBeanFactoryLocator的机制,您可以在一些地方使用,例如EJB2.0应用程序,在不能使用依赖注入的地方获取bean工厂/应用程序上下文。现有SpringContextLoader
中有一个钩子,您已经在使用它来利用这个功能,尽管设置起来有些棘手
您需要将应用程序上下文分离为父/子关系。父对象将包含服务层对象,而子对象由特定于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>
在非死亡域对象中,您可以使用以下代码访问应用程序上下文:
BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
BeanFactoryReference contextRef= locator.useBeanFactory(parentContextKey);
ApplicatonContext context = (ApplicationContext) contextRef.getFactory();
您可以在中找到有关ContextSingletonBeanFactoryLocator
的更多信息。在中关于EJB的一章中也有关于使用这种方法的详细描述。一种解决方案是使用全局静态
方法返回Spring应用程序竞赛(请参阅)
其他选项可能是让业务对象实现ApplicationContextAware
接口。在实例化时,您的“集成”代码必须将SpringApplicationContext
注入到动态创建的bean中(可能通过检查类是否实现了ApplicationContextAware
),这当然会将您的业务代码与Spring绑定,但第一个选项是相同的
一种变体是不直接注入ApplicationContext
,而是重用Spring@Autowired
注释。“集成”代码将只注入带注释的字段。创建工厂并向spring注册,使用工厂创建域对象,而不是使用“新建”
在这种情况下,您的DomainObjFactory提供的所有商品都与此略有关联
您可以采用与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);
}
}
公共接口拦截器{
创建时公共作废(对象实体);
}
公共类域工厂{
公共无效集拦截器(列表拦截器){…}
公共对象createInstance(){
//迭代拦截器,调用onCreate
}
}
公共接口MyServiceAware{
public void setMyService(MyService服务);
}
公共类MyServiceInjector实现拦截器{
私人MyService-MyService;
创建公共void(对象实体){
if(myServiceWare的实体实例)
((myserviceware)实体).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>
您可以使用非Spring托管域对象可以使用的静态getInstance()方法将依赖对象设置为单例。然后,您可以通过org.springframework.beans.factory.config.MethodInvokingFactoryBean将其提供给Spring,如下所示:
<bean id="myObject"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod">
<value>com.example.MyObject.getInstance</value>
</property>
</bean>
com.example.MyObject.getInstance
在web应用程序中执行此操作的最佳实践是什么?动态创建的域对象需要以这种方式访问SpringBean是否常见?我建议查看WebApplicationContextUtils:。我认为让Spring管理豆子更为常见。只有方法调用上下文中的本地bean才会使用“new”创建。
<bean id="myObject"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod">
<value>com.example.MyObject.getInstance</value>
</property>
</bean>