6

我有一个基于 Spring 的 webapp。我在我的控制器中使用了几个带有注释@Repository、@Transactional 的存储库类。那部分工作正常。

我创建了一个必须访问存储库的自定义约束验证器。现在我无法理解为什么存储库为空。我尝试使用 @Component 注释来注释验证器。我的包含所有这些类的基础包位于 xml 的一部分。那么我还应该做些什么来确保存储库依赖注入有效。这就是我的约束验证器的样子。

public class DonorTypeExistsConstraintValidator implements
    ConstraintValidator<DonorTypeExists, DonorType> {

  @Autowired
  private DonorTypeRepository donorTypeRepository;

  @Override
  public void initialize(DonorTypeExists constraint) {

  }

  public boolean isValid(DonorType target, ConstraintValidatorContext context) {

   System.out.println("donorType: " + target);
   if (target == null)
     return true;

   try {
    if (donorTypeRepository.isDonorTypeValid(target.getDonorType()))
     return true;
   } catch (Exception e) {
    e.printStackTrace();
   }
   return false;
  }

  public void setDonorRepository(DonorTypeRepository donorTypeRepository) {
    this.donorTypeRepository = donorTypeRepository;
  }
}

更新

包扫描配置:

<context:annotation-config />

<!-- Configures the @Controller programming model -->
<mvc:annotation-driven />

<context:component-scan base-package="controller" />
<context:component-scan base-package="repository" />
<context:component-scan base-package="model" />
<context:component-scan base-package="viewmodel" />

这个类在包model.donortype中。存储库位于包存储库中。

更新

更令人费解的是,删除所有预插入侦听器(在这种情况下只有 BeanValidationEventListener)修复了自动装配问题。这让事情变得更加复杂。

我什至没有按照下面的答案中所述插入 BeanValidationEventListener 。这实际上与这里的建议相反: JSR-303 dependency injection and Hibernate

  @Override
  public void integrate(Configuration configuration, SessionFactoryImplementor implementor,
                        SessionFactoryServiceRegistry registry) {
      logger.info("Registering event listeners");
      System.out.println("here");
      // you can add duplication strategory for duplicate registrations

      final EventListenerRegistry eventRegistry = registry.getService(EventListenerRegistry.class);
      // prepend to register before or append to register after
      // this example will register a persist event listener

      eventRegistry.prependListeners(EventType.PERSIST, EntitySaveListener.class);
      eventRegistry.appendListeners(EventType.MERGE, EntitySaveListener.class);
      Iterator<PreInsertEventListener> iter = eventRegistry.getEventListenerGroup(EventType.PRE_INSERT).listeners().iterator();
      while (iter.hasNext()) {
        PreInsertEventListener el = iter.next();
        System.out.println(el.getClass());
        BeanValidationEventListener listener = (BeanValidationEventListener) el;
        System.out.println(listener);
        iter.remove();
      }
  }

更新

我正在使用 JPA。我有 JPA 实体的支持表格。在控制器中,我使用 InitBinder 来实例化自定义验证器binder.setValidator(new EntityBackingFormValidator(binder.getValidator()));。这是代码: https ://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/controller/CollectedSampleController.java

此自定义验证器调用默认验证器上的验证,并保留执行一些自定义验证的范围。 https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/model/collectedsample/CollectedSampleBackingFormValidator.java

我在实体中使用注释来创建约束。除了默认约束之外,我还需要定义约束来检查多对一映射另一侧的实体是否存在。这是自定义约束验证器。 https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/model/donor/DonorExistsConstraintValidator.java

现在,此自定义约束验证器中的自动装配存储库为空。我正在尝试在我的 CustomIntegrator 中自定义代码,该代码位于此处 https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/src/interceptor/CustomIntegrator.java

以及此处提供的 xml 配置文件 https://github.com/C4G/V2V/blob/87dc266043f6d623c101d947a88fa0b0ad536355/war/WEB-INF/v2v-servlet.xml

希望实际代码能帮助您回答我的问题。谢谢!

4

4 回答 4

15

您使用的是哪个ValidatorFactory 。或者换一种说法,引导 Bean Validation 对你来说很热门?默认的 Bean Validation(以及作为参考实现的 Hibernate Validator)不会将依赖项注入到ConstraintValidator实例中。至少在 Bean Validation 1.0 中。

要启用依赖注入,您必须配置自定义ConstraintValidatorFactory。Spring 提供SpringConstraintValidatorFactory,这是使用LocalValidatorFactoryBean时的默认设置- 请参阅http://static.springsource.org/spring/docs/3.0.0.RC3/reference/html/ch05s07.html

另外,您使用JPA吗?我假设是这样,在这种情况下会自动对生命周期事件进行自动验证。您可以使用属性javax.persistence.validation.mode并将其设置为 NONE,而不是尝试删除事件侦听器。我想知道是否在基于生命周期的验证中使用了正确的验证器。

这完全取决于您的整体 Spring 配置和使用。

于 2012-11-29T07:35:19.637 回答
3

执行验证时是否传递了 JPA 使用的验证器工厂:

<bean 
    id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaPropertyMap">
        <map>
            <entry 
                key="javax.persistence.validation.factory"
                value-ref="validator"/>
            <!-- ... -->
        </map>
    </property>
    <!-- ... -->
</bean>

这是必需的,否则JPA 将使用默认工厂(在validation.xml中指定)。

于 2012-12-08T16:46:38.250 回答
0

DonorTypeExistsConstraintValidator 上有 @Component 注释吗?

这在过去杀死了我。

于 2012-12-07T22:24:26.273 回答
0

LocalValidatorFactoryBean 没有运气。我做了一些破解来解决这个问题。

@Component
public class ServiceUtils
{
    private static ServiceUtils instance;

    @Autowired
    private ListableBeanFactory factory;

    @PostConstruct
    public void init()
    {
        instance = this;
    }

    public static ListableBeanFactory getFactory()
    {
        return instance.factory;
    }
}
于 2016-12-22T05:34:46.633 回答