2008-10-26 2 views
1

내 응용 프로그램 용으로 개발중인 프레임 워크는 동적으로 생성 된 도메인 객체에 크게 의존합니다. 최근에 Spring WebFlow를 사용하기 시작했으며 이제는 플로우 범위에 보관 될 도메인 객체를 직렬화 할 수 있어야합니다.readResolve()와 함께 @Configurable을 사용하여 내 종속성을 주입하는 방법

나는 약간의 연구를 수행했으며 writeReplace()readResolve()을 사용할 수 있다고 생각했습니다. 유일한 캐치는 Spring 컨텍스트에서 팩토리를 검색해야한다는 것입니다. 나는 @Configurable(preConstruction = true)을 BeanFactoryAware 마커 인터페이스와 함께 사용하려고했습니다.

그러나 createEntity() 방법으로 사용하려고 시도하면 beanFactory은 항상 null입니다. 기본 생성자 또는 setBeanFactory() 인젝터가 호출되지 않습니다.

아무도 이것을 시도하지 않았습니까? 관련 수업을 아래에 포함 시켰습니다. 사전에

감사합니다,

/* 
* 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:[email protected]">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); 
    } 
} 

답변

1

브라이언 당신은 봄의 ApplicationContext, 또는 BeanFactory를 사용하고 있습니까? ApplicationContext을 사용하는 경우 대신 ApplicationContextAware를 구현할 수 있으며 Spring은 응용 프로그램 컨텍스트를 제공합니다. 나는 전에 봄의 BeanFactory을 사용한 적이 없지만 ApplicationContext을 사용했으며 작동합니다.

+0

그것은 중요하지 않습니다. 어느 쪽도 나를 위해 일하지 않는다. 문제는 preConstruction = true 옵션이 readResolve()를 통해 생성 된 객체와 함께 작동하지 않는다는 것입니다. –

0

구성 가능한 클래스가 ApsectJ 컴파일러 또는 런타임 구성으로 컴파일하여 제대로 작동하지 않았습니까?

또한 bean을 프로토 타입으로 표시하는 구성 파일의 속성을 지정해야합니다. 의 라인을 따라 뭔가 : 나는 ApplicationContextAware 또는 BeanFactoryAware와 사용 여부

<aop:spring-configured />
<bean class="package.name.SerializedCGLibEntity" scope="prototype">
<property name="beanFactory" value="whateverValue"/>
</bean>

+0

예. 그것은 확실히 weaved되었습니다. 나는 기본 생성자에 trace 문을 두었고 결코 호출되지 않는다. –

관련 문제