Java 如何使用@Configurable和readResolve()获得依赖项注入

Java 如何使用@Configurable和readResolve()获得依赖项注入,java,spring,serialization,Java,Spring,Serialization,我为我的应用程序开发的框架在很大程度上依赖于动态生成的域对象。我最近开始使用SpringWebFlow,现在需要能够序列化将保留在flow范围内的域对象 我做了一些研究,发现我可以使用writeReplace()和readResolve()。唯一的问题是我需要在Spring上下文中查找工厂。我尝试将@Configurable(preConstruction=true)与BeanFactoryAware标记接口结合使用 但是当我尝试在我的createEntity()方法中使用它时,beanFact

我为我的应用程序开发的框架在很大程度上依赖于动态生成的域对象。我最近开始使用SpringWebFlow,现在需要能够序列化将保留在flow范围内的域对象

我做了一些研究,发现我可以使用
writeReplace()
readResolve()
。唯一的问题是我需要在Spring上下文中查找工厂。我尝试将
@Configurable(preConstruction=true)
与BeanFactoryAware标记接口结合使用

但是当我尝试在我的
createEntity()
方法中使用它时,
beanFactory
总是
null
。既不调用默认构造函数也不调用
setBeanFactory()
injector

有人试过这个或类似的吗?我已经包括了下面的相关课程

提前感谢,, 布莱恩

/*
*版权所有2008布莱恩·托马斯·马修斯有限公司。
*版权所有,世界各地。
*
*本软件及其包含的所有信息均为
*布莱恩·托马斯·马修斯有限公司。任何传播、披露、使用或
*因与合同不一致的任何原因复制本材料
*严禁出于明示目的披露。
*/
包com.btmatthews.dmf.domain.impl.cglib;
导入java.io.InvalidObject异常;
导入java.io.ObjectStreamException;
导入java.io.Serializable;
导入java.lang.reflect.InvocationTargetException;
导入java.util.HashMap;
导入java.util.Map;
导入org.apache.commons.beanutils.PropertyUtils;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.springframework.beans.factory.BeanFactory;
导入org.springframework.beans.factory.BeanFactoryAware;
导入org.springframework.beans.factory.annotation.Configurable;
导入org.springframework.util.StringUtils;
导入com.btmatthews.dmf.domain.IEntity;
导入com.btmatthews.dmf.domain.IEntityFactory;
导入com.btmatthews.dmf.domain.IEntityID;
导入com.btmatthews.dmf.spring.IEntityDefinitionBean;
/**
*此类表示实现的域对象的序列化形式
*使用CGLib。readResolve()方法重新创建实际的域对象
*将其反序列化为可序列化后。你必须定义
*spring已在应用程序上下文中配置/删除。
* 
*@param
*定义基域属性的接口
*反对。
*@param
*定义派生域属性的接口
*反对。
*@作者
*@version 1.0
*/
@可配置(预构造=真)
公共最终类序列化dGlibentity
实现可序列化、BeanFactoryAware
{
/**
*用于日志记录。
*/
专用静态最终记录器日志=LoggerFactory
.getLogger(SerializedGlibentity.class);
/**
*序列化版本号。
*/
私有静态最终长serialVersionUID=3830830321957878319L;
/**
*应用程序上下文。注意,这不是序列化的。
*/
私人临时工厂;
/**
*域对象名。
*/
私有字符串entityName;
/**
*域对象标识符。
*/
私有的IEntityID实体ID;
/**
*域对象版本号。
*/
私有长实体版本;
/**
*域对象的属性。
*/
私有HashMap实体属性;
/**
*默认构造函数。
*/
公共数据集glibentity()
{
SerializedGlibentity.LOG
.debug(“使用默认构造函数初始化”);
}
/**
*使用要序列化的属性初始化。
* 
*@param name
*实体名称。
*@param-id
*域对象标识符。
*@param版本
*实体版本。
*@param属性
*实体属性。
*/
public serializedGlibentity(最终字符串名、最终IEntityID、,
最终长版本,最终HashMap属性)
{
SerializedGlibentity.LOG
.debug(“使用参数化构造函数初始化”);
this.entityName=名称;
this.entityId=id;
this.entityVersion=版本;
this.entityAttributes=属性;
}
/**
*注入豆子工厂。
* 
*@param工厂
*豆子工厂。
*/
公共工厂(最终工厂)
{
SerializedGlibentity.LOG.debug(“注入的bean工厂”);
this.beanFactory=工厂;
}
/**
*反序列化后调用。相应的实体工厂为
*从bean应用程序上下文检索,BeanUtils方法是
*用于初始化对象。
* 
*@返回初始化的域对象。
*@ObjectStreamException
*如果创建或初始化域时出现问题
*反对。
*/
公共对象readResolve()
抛出对象流异常
{
SerializedGlibentity.LOG.debug(“转换反序列化对象”);
最终的T实体=this.createEntity();
entity.setId(this.entityId);
尝试
{
PropertyUtils.setSimpleProperty(实体,“版本”,
这是一个完整的版本);
对于(Map.Entry:this.entityAttributes.entrySet())
{
PropertyUtils.setSimpleProperty(实体,entry.getKey()
.toString(),entry.getValue());
}
}
捕获(非法访问例外e)
{
抛出新的InvalidObjectException(例如getMessage());
}
捕获(调用TargetException e)
{
抛出新的InvalidObjectException(例如getMessage());
}
ca
/*
 *  Copyright 2008 Brian Thomas Matthews Limited.
 *  All rights reserved, worldwide.
 *
 *  This software and all information contained herein is the property of
 *  Brian Thomas Matthews Limited. Any dissemination, disclosure, use, or
 *  reproduction of this material for any reason inconsistent with the
 *  express purpose for which it has been disclosed is strictly forbidden.
 */

package com.btmatthews.dmf.domain.impl.cglib;

import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.util.StringUtils;

import com.btmatthews.dmf.domain.IEntity;
import com.btmatthews.dmf.domain.IEntityFactory;
import com.btmatthews.dmf.domain.IEntityID;
import com.btmatthews.dmf.spring.IEntityDefinitionBean;

/**
 * This class represents the serialized form of a domain object implemented
 * using CGLib. The readResolve() method recreates the actual domain object
 * after it has been deserialized into Serializable. You must define
 * <spring-configured/> in the application context.
 * 
 * @param <S>
 *            The interface that defines the properties of the base domain
 *            object.
 * @param <T>
 *            The interface that defines the properties of the derived domain
 *            object.
 * @author <a href="mailto:brian@btmatthews.com">Brian Matthews</a>
 * @version 1.0
 */
@Configurable(preConstruction = true)
public final class SerializedCGLibEntity<S extends IEntity<S>, T extends S>
    implements Serializable, BeanFactoryAware
{
    /**
     * Used for logging.
     */
    private static final Logger LOG = LoggerFactory
        .getLogger(SerializedCGLibEntity.class);

    /**
     * The serialization version number.
     */
    private static final long serialVersionUID = 3830830321957878319L;

    /**
     * The application context. Note this is not serialized.
     */
    private transient BeanFactory beanFactory;

    /**
     * The domain object name.
     */
    private String entityName;

    /**
     * The domain object identifier.
     */
    private IEntityID<S> entityId;

    /**
     * The domain object version number.
     */
    private long entityVersion;

    /**
     * The attributes of the domain object.
     */
    private HashMap<?, ?> entityAttributes;

    /**
     * The default constructor.
     */
    public SerializedCGLibEntity()
    {
        SerializedCGLibEntity.LOG
            .debug("Initializing with default constructor");
    }

    /**
     * Initialise with the attributes to be serialised.
     * 
     * @param name
     *            The entity name.
     * @param id
     *            The domain object identifier.
     * @param version
     *            The entity version.
     * @param attributes
     *            The entity attributes.
     */
    public SerializedCGLibEntity(final String name, final IEntityID<S> id,
        final long version, final HashMap<?, ?> attributes)
    {
        SerializedCGLibEntity.LOG
            .debug("Initializing with parameterized constructor");

        this.entityName = name;
        this.entityId = id;
        this.entityVersion = version;
        this.entityAttributes = attributes;
    }

    /**
     * Inject the bean factory.
     * 
     * @param factory
     *            The bean factory.
     */
    public void setBeanFactory(final BeanFactory factory)
    {
        SerializedCGLibEntity.LOG.debug("Injected bean factory");

        this.beanFactory = factory;
    }

    /**
     * Called after deserialisation. The corresponding entity factory is
     * retrieved from the bean application context and BeanUtils methods are
     * used to initialise the object.
     * 
     * @return The initialised domain object.
     * @throws ObjectStreamException
     *             If there was a problem creating or initialising the domain
     *             object.
     */
    public Object readResolve()
        throws ObjectStreamException
    {
        SerializedCGLibEntity.LOG.debug("Transforming deserialized object");

        final T entity = this.createEntity();
        entity.setId(this.entityId);
        try
        {
            PropertyUtils.setSimpleProperty(entity, "version",
            this.entityVersion);
            for (Map.Entry<?, ?> entry : this.entityAttributes.entrySet())
            {
                PropertyUtils.setSimpleProperty(entity, entry.getKey()
                    .toString(), entry.getValue());
            }
        }
        catch (IllegalAccessException e)
        {
            throw new InvalidObjectException(e.getMessage());
        }
        catch (InvocationTargetException e)
        {
            throw new InvalidObjectException(e.getMessage());
        }
        catch (NoSuchMethodException e)
        {
            throw new InvalidObjectException(e.getMessage());
        }
        return entity;
    }

    /**
     * Lookup the entity factory in the application context and create an
     * instance of the entity. The entity factory is located by getting the
     * entity definition bean and using the factory registered with it or
     * getting the entity factory. The name used for the definition bean lookup
     * is ${entityName}Definition while ${entityName} is used for the factory
     * lookup.
     * 
     * @return The domain object instance.
     * @throws ObjectStreamException
     *             If the entity definition bean or entity factory were not
     *             available.
     */
    @SuppressWarnings("unchecked")
    private T createEntity()
        throws ObjectStreamException
    {
        SerializedCGLibEntity.LOG.debug("Getting domain object factory");

        // Try to use the entity definition bean

        final IEntityDefinitionBean<S, T> entityDefinition = (IEntityDefinitionBean<S, T>)this.beanFactory
            .getBean(StringUtils.uncapitalize(this.entityName) + "Definition",
                IEntityDefinitionBean.class);

        if (entityDefinition != null)
        {
            final IEntityFactory<S, T> entityFactory = entityDefinition
                .getFactory();
            if (entityFactory != null)
            {
                 SerializedCGLibEntity.LOG
                    .debug("Domain object factory obtained via enity definition bean");

                 return entityFactory.create();
            }
        }

        // Try to use the entity factory

        final IEntityFactory<S, T> entityFactory = (IEntityFactory<S, T>)this.beanFactory
            .getBean(StringUtils.uncapitalize(this.entityName) + "Factory",
                IEntityFactory.class);

        if (entityFactory != null)
        {
            SerializedCGLibEntity.LOG
                .debug("Domain object factory obtained via direct look-up");

            return entityFactory.create();
        }

        // Neither worked!

        SerializedCGLibEntity.LOG.warn("Cannot find domain object factory");

        throw new InvalidObjectException(
            "No entity definition or factory found for " + this.entityName);
    }
}