2015-06-18 4 views
0

Я внедрил валидатор enum после более старых сообщений здесь. Мне было интересно, является ли этот следующий код потокобезопасным или нет? У меня есть много разных перечислений, для которых мне нужно использовать этот валидатор. Это вызовет проблемы?Является ли следующая проверка валидатора enum безопасной?

@Documented 
@Constraint(validatedBy = StringEnumerationValidator.class) 
@Target({ElementType.FIELD,ElementType.ANNOTATION_TYPE, 
ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) 
@Retention(RetentionPolicy.RUNTIME) 
@NotNull(message="Value must not be null.") 
public @interface StringEnumeration { 

    String message() default "{com.xxx.bean.validation.constraints.StringEnumeration.message}"; 
    Class<?>[] groups() default{}; 
    Class<? extends Payload>[] payload() default{}; 
    Class<? extends Enum<?>> enumClass(); 
} 


public class StringEnumerationValidator implements 
    ConstraintValidator<StringEnumeration, String> { 

    private Set<String> AVAILABLE_ENUM_NAMES; 

    public static Set<String> getNamesSet(Class<? extends Enum<?>> e){ 
     Enum<?>[] enums = e.getEnumConstants(); 
     String[] names = new String[enums.length]; 
     for (int i = 0; i < enums.length; i++) { 
      names[i] = enums[i].name(); 
      System.out.println(enums.length); 
      System.out.println(enums[i]); 
     } 
     Set<String> mySet = new HashSet<String>(Arrays.asList(names)); 
     return mySet; 
    } 

    @Override 
    public void initialize(StringEnumeration stringEnumeration) { 
     Class<? extends Enum<?>> enumSelected = stringEnumeration.enumClass(); 
     AVAILABLE_ENUM_NAMES = getNamesSet(enumSelected); 

    } 
    @Override 
    public boolean isValid(String value, ConstraintValidatorContext context) { 
     if (value == null) { 
     return true; 
     } 
     else { 
      return AVAILABLE_ENUM_NAMES.contains(value); 
     } 

    } 

EDIT: Источники называют:

+0

Поскольку ваш метод isValid делает только чтение, он является потокобезопасным, предполагая, что структура проверки подчиняется контракту не вызывать 'isValid' до завершения' initialize'. – Holger

+0

Обновлены теги, исправлены опечатки и удалены. Добавьте ссылки на «старшие сообщения», на которые вы ссылаетесь. – Ram

+0

@Ram Добавлены источники. –

ответ

0

Да и нет. Строго говоря, он не является потокобезопасным, потому что ваш метод initialize можно было бы вызывать одновременно двумя разными потоками. Этот метод записывает в переменную AVAILABLE_ENUM_NAMES, и, таким образом, эти два потока могут мешать друг другу.

Но если вы убедитесь, что initialize вызывается только один раз для каждого экземпляра, перед тем как другие потоки имеют доступ к этому экземпляру, он является потокобезопасным, потому что isValid только считывает набор и не изменяет его.

Чтобы гарантировать, что инициализация выполняется только один раз, вы должны сделать это в конструкторе:

public StringEnumeratorValidator(StringEnumeration stringEnumeration) { 
    Class<? extends Enum<?>> enumSelected = stringEnumeration.enumClass(); 
    AVAILABLE_ENUM_NAMES = getNamesSet(enumSelected); 
} 

и удалить метод intialize.

Смежные вопросы