管理Springbeans创建和字典

管理Springbeans创建和字典,spring,spring-bean,Spring,Spring Bean,我必须管理bean实例和某种类型的资源之间的关联。更具体地说,当我接收到与资源A相关联的一些数据时,每次我接收到与指定资源相关联的数据时,我都必须将数据分派给CREATEA,以创建某个bean类型的实例。例如,如果我收到一些与资源“a”关联的数据,那么我必须将这些数据分派给与“a”关联的Bean实例。如果没有与资源“a”关联的Bean实例,那么必须创建它。资源的数量不是静态已知的,只有在执行期间才知道 我知道我需要某种类型的字典来存储资源id和bean实例之间的关联,构建类似于工厂的东西来管理b

我必须管理bean实例和某种类型的资源之间的关联。更具体地说,当我接收到与资源A相关联的一些数据时,每次我接收到与指定资源相关联的数据时,我都必须将数据分派给CREATEA,以创建某个bean类型的实例。例如,如果我收到一些与资源“a”关联的数据,那么我必须将这些数据分派给与“a”关联的Bean实例。如果没有与资源“a”关联的Bean实例,那么必须创建它。资源的数量不是静态已知的,只有在执行期间才知道

我知道我需要某种类型的字典来存储资源id和bean实例之间的关联,构建类似于工厂的东西来管理bean的创建。
我如何在春天实现这一点?正确的方法是什么?

可以用这种“字典”方式引用Spring
ApplicationContext
。也就是说,您向应用程序上下文指定“设置”资源bean。然后通过
map
对象映射“接收到的数据”,该对象反过来持有对bean的引用。一旦数据映射到bean,就可以检索bean并处理接收到的数据。这里有一个简单的例子

这是一个资源服务接口

package de.incompleteco.spring.service;

public interface ResourceService {

    public void processData(Object data);

}
下面是一个处理“TypeA”数据的实现

package de.incompleteco.spring.service;

public class TypeAResourceService implements ResourceService {

    public void processData(Object data) {
        //do something for 'type A' data
    }

}
这里有一个“委托”服务

package de.incompleteco.spring.service;

import java.util.Map;

import de.incompleteco.spring.domain.TypeA;
import de.incompleteco.spring.domain.TypeB;

public class DelegateResourceService implements ResourceService {

    private Map<String,ResourceService> services;

    public void processData(Object data) {
        if (data instanceof TypeA) {
            services.get(TypeA.class.getSimpleName()).processData(data);
        } else if (data instanceof TypeB) {
            services.get(TypeA.class.getSimpleName()).processData(data);
        } else {
            throw new IllegalArgumentException("...");
        }
    }

    public void setServices(Map<String, ResourceService> services) {
        this.services = services;
    }

}
package de.incompleteco.spring.service;
导入java.util.Map;
导入de.incompleteco.spring.domain.TypeA;
导入de.incompleteco.spring.domain.TypeB;
公共类DelegateResourceService实现ResourceService{
私人地图服务;
公共void processData(对象数据){
if(类型A的数据实例){
getservices.get(TypeA.class.getSimpleName()).processData(data);
}else if(类型B的数据实例){
getservices.get(TypeA.class.getSimpleName()).processData(data);
}否则{
抛出新的IllegalArgumentException(“…”);
}
}
公共void设置服务(地图服务){
这是服务=服务;
}
}
“委托”服务负责从映射中检索正确的服务以处理正确的数据(按类名键入)

下面是要支持的spring配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- type 'a' bean -->
    <bean id="typeA" class="de.incompleteco.spring.service.TypeAResourceService"/>

    <!-- type 'b' bean -->
    <bean id="typeB" class="de.incompleteco.spring.service.TypeBResourceService"/>

    <util:map id="dictionary">
        <entry key="TypeA" value-ref="typeA"/>
        <entry key="TypeB" value-ref="typeB"/>
    </util:map>

    <bean class="de.incompleteco.spring.service.DelegateResourceService">
        <property name="services" ref="dictionary"/>
    </bean>

</beans>

此配置执行以下操作:

  • 为类型A和B数据设置服务
  • 将这些服务映射到密钥
  • 设置代理服务,设置要使用的映射
这种模式不是唯一的方法,但它给你以下

  • 能够独立地配置服务bean
  • 代理只需要一个映射即可进行处理
  • 约束条件是服务对象必须具有相同的接口

您可以将Spring ApplicationContext视为一个巨大的工厂,但(在许多方面)设置起来要简单得多。

mmmmm谢谢您的建议,但有一个问题:我不知道静态情况下我将获得哪些资源。不要以类型化的方式思考资源(
TypeA
TypeB
),而是以基于动态值的方式思考资源(
resource.getValue()==“a”
resource.getValue()==“b”
,其中可能的值未知)。通过这种方式,我无法在配置文件中指定映射值,但我需要类似以下内容:
if(!map.contains(resource.getValue())createDelegate(resource);
。如果键的数量是无限的,则缓存会导致内存泄漏;如果键的数量是常数,则可以查看对象的数量并在之前创建bean。如果存在(类似散列的)将密钥投影到某个较小的有限密钥集的函数可能会起作用,但无论如何,通过创建单独的bean进行缓存对我来说似乎很奇怪。我想你应该将缓存移到某个较低级别的抽象,并使用spring缓存功能,而不是创建bean。即缓存服务返回的一些DTO或实体当然,bean将是有限的,并且与应用程序交互的用户数量将更少(使用每个会话范围的bean将导致更多的bean)。