Создание Spring Bean с помощью десериализации - PullRequest
1 голос
/ 27 апреля 2010

В Spring есть много разных способов создания bean-компонентов, но возможно ли создать bean-компонент путем десериализации ресурса?

Мое приложение имеет несколько компонентов, и каждый из них управляет определенным типом данных. Во время тестирования объект данных создается непосредственно и устанавливается непосредственно на компонент, например, component.setData (someDataObject). Во время выполнения данные доступны как сериализованный объект и считываются компонентом из сериализованного потока (поток передается как ресурс из контекста Spring.)

Вместо того, чтобы каждый компонент явно десериализовал свои данные из потока, было бы более согласованным и гибким, если бы Spring десериализовал объект данных из ресурса и установил его в целевом компоненте. Таким образом, компоненты изолируются от того, откуда поступают их данные.

Есть ли DeserializerFactoryBean или что-то подобное?

EDIT:

Вот пример кода, который мы надеемся уточнить:

public class ComponentData implements Externalizable
{
   // a complex data structure, behind a simpler interface       
}

public class Component
{
   private ComponenttData  componentData;

   public Component(ComponentData data)
   {
      componentData = data;
   }

   // other methods that operate using the data

   // factory method to create from serialized data
   static Component createFromResource(Resource resource)
   {
       return new Component(deserialize(resource));
   }
}

Существует много типов компонентов, и каждый тип компонента создается несколько раз с различными экземплярами данных.

В тесте Компоненты и их экземпляры ComponentData строятся в коде. В производстве пружинный компонент с атрибутом «factory-method» используется для вызова статического метода Componnet.createFromResource, который десериализует данные из ресурса. Существует много типов компонентов, и у каждого из них один и тот же статический метод для построения из десериализованных данных. Это само по себе кажется плохим из-за повторения. Мне также кажется странным, что конструкция компонентов при испытаниях и производстве не совпадают. Если десериализацию можно перенести в контекст Spring, статические методы для Компонентов можно удалить, и тогда вся инъекция зависимостей выполняется Spring вместо необходимости кодировать это как особый случай.

например. Я представляю что-то вроде

<bean name="componentData" class="DeserializingFactoryBean">
    <constructor-arg value="/data/componentData1.dat"/> <!--  resource -->
</bean>

<bean name="component" class="Component">
    <constructor-arg ref="componentData"/>
</bean>

Когда я первоначально писал, я думал, что это может существовать, но я, что я мог пропустить в огромных весенних javadocs. Судя по первоначальным ответам, Spring не имеет десериализованного фабричного компонента.

Если DeserializingFactoryBean не является правильным подходом, какие альтернативы существуют?

Ответы [ 3 ]

0 голосов
/ 27 апреля 2010

Да, вы можете реализовать свой собственный Beanfactory, как сделано для SimpleJndiBeanFactory. Но я не уверен, это то, что вы хотите. Вам нужны дополнительные компоненты в контексте приложения. Я бы реализовал BeanFactoryPostProcessor загрузку бобов из потока и autowire или регистрация их.

0 голосов
/ 30 апреля 2010

То, что другие постеры для их комментариев. Как они отмечали, в Spring нет поддержки фабрики десериализации, поэтому я ее создал.

Ниже приведен код для FactoryBean , который создает компоненты с помощью десериализации из ресурса. По умолчанию создается один экземпляр, и один и тот же экземпляр возвращается для каждого использования. Вы можете установить для свойства singleton значение false, и новый экземпляр будет десериализован при каждом использовании.

Используется вот так

<bean name="myBean" class="DeserializingFactoryBean">
    <property name="source" value="mybean.ser"/>
    <property name="objectType" value="org.acme.MyBean"/>
</bean>

и код

import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

import java.io.BufferedInputStream;
import java.io.ObjectInputStream;

public class DeserializingFactoryBean extends AbstractFactoryBean
{
    private Resource    source;

    private Class<?>    objectType;

    private int         deserializationCount;

    public DeserializingFactoryBean()
    {
    }

    public DeserializingFactoryBean(Resource source, Class<?> objectType)
    {
        this.source = source;
        this.objectType = objectType;
    }

    public void afterPropertiesSet() throws Exception
    {
        Assert.notNull(objectType, "Property 'objectType' may not be null");
        Assert.notNull(source, "Property 'source' may not be null");
        super.afterPropertiesSet();
    }

    public Resource getSource()
    {
        return source;
    }

    public void setSource(Resource source)
    {
        this.source = source;
    }

    public void setObjectType(Class<?> objectType)
    {
        this.objectType = objectType;
    }

    public Class getObjectType()
    {
        return objectType;
    }

    @Override
    protected Object createInstance() throws Exception
    {
        ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(source.getInputStream()));
        Object result = oin.readObject();
        if (!objectType.isInstance(result))
            throw new ClassCastException(String.format("Deserialized object is not an instance of %s",objectType.getName()));
        oin.close();
        return result;
    }
}
0 голосов
/ 27 апреля 2010

Есть ли DeserializerBeanFactory или что-то подобное?

Никогда не слышал об этом, и, честно говоря, я бы не хотел, чтобы моей инициализацией управляли непрозрачные (для простого человека) сериализованные объекты.

Но если вы действительно думаете, что это хорошая идея (хм), не должно быть трудностей с созданием пользовательского BeanFactory, который работал бы таким образом.

...