JavaRush/ΠšΡƒΡ€ΡΡ‹/ΠœΠΎΠ΄ΡƒΠ»ΡŒ 5. Spring/ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° Π² Spring

ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° Π² Spring

ΠžΡ‚ΠΊΡ€Ρ‹Ρ‚Π°

Π’ Spring 3 появился ΠΏΠ°ΠΊΠ΅Ρ‚ core.convert, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдоставляСт ΠΎΠ±Ρ‰ΡƒΡŽ систСму прСобразования Ρ‚ΠΈΠΏΠΎΠ². БистСма опрСдСляСт SPI (интСрфСйс поставщика слуТб) для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π»ΠΎΠ³ΠΈΠΊΠΈ прСобразования Ρ‚ΠΈΠΏΠΎΠ² ΠΈ API-интСрфСйса для осущСствлСния прСобразования Ρ‚ΠΈΠΏΠΎΠ² Π²ΠΎ врСмя выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. Π’ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅ Spring ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ эту систСму ΠΊΠ°ΠΊ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Ρƒ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ PropertyEditor для прСобразования ΠΈΠ·Π²Π»Π΅Ρ‡Ρ‘Π½Π½Ρ‹Ρ… строк Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ свойств Π±ΠΈΠ½Π° Π² Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹Π΅ Ρ‚ΠΈΠΏΡ‹ свойств. Π’Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Ρ‹ΠΉ API-интСрфСйс Π² любом мСстС вашСго прилоТСния, Π³Π΄Π΅ трСбуСтся ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠΎΠ².

SPI-интСрфСйс Converter

SPI-интСрфСйс для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π»ΠΎΠ³ΠΈΠΊΠΈ прСобразования Ρ‚ΠΈΠΏΠΎΠ² являСтся простым ΠΈ сильно Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌ, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΈ интСрфСйса:

package org.springframework.core.convert.converter;
public interface Converter<S, T> {
    T convert(S source);
}

Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ свой собствСнный ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠΉΡ‚Π΅ интСрфСйс Converter ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ S ΠΊΠ°ΠΊ Ρ‚ΠΈΠΏ, ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π²Ρ‹ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚Π΅, ΠΈ T ΠΊΠ°ΠΊ Ρ‚ΠΈΠΏ, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²Ρ‹ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚Π΅. МоТно Ρ‚Π°ΠΊΠΆΠ΅ понятным способом ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ Ρ‚Π°ΠΊΠΎΠΉ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ, Ссли ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡŽ ΠΈΠ»ΠΈ массив S Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Π² массив ΠΈΠ»ΠΈ ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡŽ T, ΠΏΡ€ΠΈ условии, Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π΅Π³ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ массивов ΠΈΠ»ΠΈ ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΉ Ρ‚Π°ΠΊΠΆΠ΅ зарСгистрирован (Ρ‡Ρ‚ΠΎ DefaultConversionService Π΄Π΅Π»Π°Π΅Ρ‚ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ).

Для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° convert(S) исходный Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎ Π½Π΅ являСтся пустым (null). Π’Π°Ρˆ Converter ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠ³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ любоС нСпровСряСмоС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Ссли ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π΅ ΡƒΠ΄Π°Π»ΠΎΡΡŒ. Π’ частности, ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ IllegalArgumentException, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠΎΠΎΠ±Ρ‰Π°Ρ‚ΡŒ ΠΎ нСдопустимом Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΈ источника. ΠžΠ·Π°Π±ΠΎΡ‚ΡŒΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ваша рСализация Converter Π±Ρ‹Π»Π° потокобСзопасной.

НСсколько Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΉ прСобразоватСля для удобства прСдоставлСны Π² ΠΏΠ°ΠΊΠ΅Ρ‚Π΅ core.convert.support. Они Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΈΠ· строк Π² числа ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ распространСнныС Ρ‚ΠΈΠΏΡ‹. Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ листингС ΠΏΠΎΠΊΠ°Π·Π°Π½ класс StringToInteger, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ являСтся Ρ‚ΠΈΠΏΠΈΡ‡Π½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Converter:

package org.springframework.core.convert.support;
final class StringToInteger implements Converter<String, Integer> {
    public Integer convert(String source) {
        return Integer.valueOf(source);
    }
}

ИспользованиС ConverterFactory

Если Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π»ΠΎΠ³ΠΈΠΊΡƒ прСобразования для всСй ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΠΈ классов (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΏΡ€ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠΈ ΠΈΠ· ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² String Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Enum), ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ConverterFactory, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅:

package org.springframework.core.convert.converter;
public interface ConverterFactory<S, R> {
    <T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ S ΠΊΠ°ΠΊ Ρ‚ΠΈΠΏ, ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π²Ρ‹ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Π΅Ρ‚Π΅, Π° R ΠΊΠ°ΠΊ Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ Ρ‚ΠΈΠΏ, ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰ΠΈΠΉ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½ классов, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ. Π—Π°Ρ‚Π΅ΠΌ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠΉΡ‚Π΅ getConverter(Class<T>)), Π³Π΄Π΅ T являСтся подклассом R.

Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° рассмотрим StringToEnumConverterFactory:

package org.springframework.core.convert.support;
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnumConverter(targetType);
    }
    private final class StringToEnumConverter<T extends Enum> implements Converter<String, T> {
        private Class<T> enumType;
        public StringToEnumConverter(Class<T> enumType) {
            this.enumType = enumType;
        }
        public T convert(String source) {
            return (T) Enum.valueOf(this.enumType, source.trim());
        }
    }
}

ИспользованиС GenericConverter

Если Π²Π°ΠΌ трСбуСтся слоТная рСализация Converter, Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ΡΡŒ интСрфСйсом GenericConverter. GenericConverter с Π±ΠΎΠ»Π΅Π΅ Π³ΠΈΠ±ΠΊΠΎΠΉ, Π½ΠΎ ΠΌΠ΅Π½Π΅Π΅ строго Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ Converter сигнатурой, ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ нСсколькими исходными ΠΈ Ρ†Π΅Π»Π΅Π²Ρ‹ΠΌΠΈ Ρ‚ΠΈΠΏΠ°ΠΌΠΈ. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, GenericConverter Π΄Π΅Π»Π°Π΅Ρ‚ доступным контСкст исходного ΠΈ Ρ†Π΅Π»Π΅Π²ΠΎΠ³ΠΎ поля, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π»ΠΎΠ³ΠΈΠΊΠΈ прСобразования. Π’Π°ΠΊΠΎΠΉ контСкст позволяСт ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Ρ‚ΠΈΠΏΡ‹ Π½Π° основС Π°Π½Π½ΠΎΡ‚Π°Ρ†ΠΈΠΈ поля ΠΈΠ»ΠΈ ΠΎΠ±Ρ‰Π΅ΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ, объявлСнной Π² сигнатурС поля. Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ листингС ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ интСрфСйса GenericConverter:

package org.springframework.core.convert.converter;
public interface GenericConverter {
    public Set<ConvertiblePair> getConvertibleTypes();
    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}

Для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ GenericConverter Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ функция getConvertibleTypes() Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π»Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ ΠΏΠ°Ρ€Ρ‹ Ρ‚ΠΈΠΏΠΎΠ² ΠΈΡΡ‚ΠΎΡ‡Π½ΠΈΠΊβ†’Ρ†Π΅Π»ΡŒ. Π—Π°Ρ‚Π΅ΠΌ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠΉΡ‚Π΅ convert(Object, TypeDescriptor, TypeDescriptor), Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π»ΠΎΠ³ΠΈΠΊΡƒ прСобразования. TypeDescriptor источника прСдоставляСт доступ ΠΊ полю источника, содСрТащСму ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. TypeDescriptor Ρ†Π΅Π»ΠΈ обСспСчиваСт доступ ΠΊ Ρ†Π΅Π»Π΅Π²ΠΎΠΌΡƒ полю, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ установлСно ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.

Π₯ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠΌ GenericConverter являСтся ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ массив Java Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΡŽ. Π’Π°ΠΊΠΎΠΉ ArrayToCollectionConverter ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚ самоанализ поля, ΠΎΠ±ΡŠΡΠ²Π»ΡΡŽΡ‰Π΅Π³ΠΎ Ρ‚ΠΈΠΏ Ρ†Π΅Π»Π΅Π²ΠΎΠΉ ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Ρ‚ΠΈΠΏ элСмСнта ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ. Π­Ρ‚ΠΎ позволяСт ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт исходного массива Π² Ρ‚ΠΈΠΏ элСмСнта ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ коллСкция Π±ΡƒΠ΄Π΅Ρ‚ установлСна Π² Ρ†Π΅Π»Π΅Π²ΠΎΠ΅ ΠΏΠΎΠ»Π΅.

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ GenericConverter являСтся Π±ΠΎΠ»Π΅Π΅ слоТным SPI-интСрфСйсом, Π΅Π³ΠΎ слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² случаС нСобходимости. Для Π±Π°Π·ΠΎΠ²Ρ‹Ρ… Π½ΡƒΠΆΠ΄ прСобразования Ρ‚ΠΈΠΏΠΎΠ² ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Converter ΠΈΠ»ΠΈ ConverterFactory.

ИспользованиС ConditionalGenericConverter

Иногда трСбуСтся, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Converter запускался Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ условия. НапримСр, Π²Π°ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Converter, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ссли Π² Ρ†Π΅Π»Π΅Π²ΠΎΠΌ ΠΏΠΎΠ»Π΅ присутствуСт опрСдСлСнная аннотация, ΠΈΠ»ΠΈ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Converter, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ссли Π² Ρ†Π΅Π»Π΅Π²ΠΎΠΌ классС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΌΠ΅Ρ‚ΠΎΠ΄ static valueOf). ConditionalGenericConverter – это объСдинСниС интСрфСйсов GenericConverter ΠΈ ConditionalConverter, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰Π΅Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ Ρ‚Π°ΠΊΠΈΠ΅ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΡ€ΠΈΡ‚Π΅Ρ€ΠΈΠΈ соотвСтствия:

public interface ConditionalConverter {
    boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
}

Π₯ΠΎΡ€ΠΎΡˆΠΈΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠΌ ConditionalGenericConverter являСтся IdToEntityConverter, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ осущСствляСт ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ постоянным ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ сущности ΠΈ ссылкой Π½Π° ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ. Π’Π°ΠΊΠΎΠΉ IdToEntityConverter ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ подходящим, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ссли Ρ†Π΅Π»Π΅Π²ΠΎΠΉ Ρ‚ΠΈΠΏ сущности ΠΎΠ±ΡŠΡΠ²Π»ΡΠ΅Ρ‚ статичСский поисковый ΠΌΠ΅Ρ‚ΠΎΠ΄ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, findAccount(Long)). Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ Ρ‚Π°ΠΊΡƒΡŽ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ поискового ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Π² Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ matches(TypeDescriptor, TypeDescriptor).

API ConversionService

ConversionService опрСдСляСт ΡƒΠ½ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ API для выполнСния Π»ΠΎΠ³ΠΈΠΊΠΈ прСобразования Ρ‚ΠΈΠΏΠΎΠ² Π²ΠΎ врСмя выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ Π·Π°Ρ‡Π°ΡΡ‚ΡƒΡŽ Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ послС ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ фасадного интСрфСйса:

package org.springframework.core.convert;
public interface ConversionService {
    boolean canConvert(Class<?> sourceType, Class<?> targetType);
    <T> T convert(Object source, Class<T> targetType);
    boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);
    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}

Π‘ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΉ ConversionService Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‚ ConverterRegistry, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдоставляСт SPI-интСрфСйс для рСгистрации ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ. Π’Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅ рСализация ConversionService Π΄Π΅Π»Π΅Π³ΠΈΡ€ΡƒΠ΅Ρ‚ своим зарСгистрированным прСобразоватСлям Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π»ΠΎΠ³ΠΈΠΊΠΈ прСобразования Ρ‚ΠΈΠΏΠΎΠ².

НадСТная рСализация ConversionService прСдоставляСтся Π² ΠΏΠ°ΠΊΠ΅Ρ‚Π΅ core.convert.support. GenericConversionService – это рСализация ΠΎΠ±Ρ‰Π΅Π³ΠΎ назначСния, подходящая для использования Π² Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π΅ срСд. ConversionServiceFactory прСдоставляСт ΡƒΠ΄ΠΎΠ±Π½ΡƒΡŽ Ρ„Π°Π±Ρ€ΠΈΠΊΡƒ для создания ΠΎΠ±Ρ‰ΠΈΡ… ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΉ ConversionService.

ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ConversionService

ConversionService – это ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, Π½Π΅ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‰ΠΈΠΉ состояниС, экзСмпляр ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ создаСтся ΠΏΡ€ΠΈ запускС прилоТСния ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ совмСстного использования нСсколькими ΠΏΠΎΡ‚ΠΎΠΊΠ°ΠΌΠΈ. Π’ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ Π½Π° Spring экзСмпляр ConversionService ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ конфигурируСтся для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° Spring (ΠΈΠ»ΠΈ ApplicationContext). Spring опрСдСляСт этот ConversionService ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π΅Π³ΠΎ всякий Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΡƒ Π½ΡƒΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠ°. Π’Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ½ΠΎ Π²Π½Π΅Π΄Ρ€ΠΈΡ‚ΡŒ этот ConversionService Π² любой ΠΈΠ· Π²Π°ΡˆΠΈΡ… Π±ΠΈΠ½ΠΎΠ² ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Π΅Π³ΠΎ Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ.

Если Π² Spring Π½Π΅ зарСгистрирован ConversionService, Ρ‚ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½Π°Ρ систСма Π½Π° основС PropertyEditor.

Π§Ρ‚ΠΎΠ±Ρ‹ Π·Π°Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² Spring стандартный ConversionService, Π΄ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π±ΠΈΠ½Π° с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ΠΌ id Π² Π²ΠΈΠ΄Π΅ conversionService:

<bean id="conversionService"
    class="org.springframework.context.support.ConversionServiceFactoryBean"/>

Π‘Ρ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½Ρ‹ΠΉ ConversionService ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ строки, числа, пСрСчисляСмыС Ρ‚ΠΈΠΏΡ‹, ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΈ, ассоциативныС массивы ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ распространСнныС Ρ‚ΠΈΠΏΡ‹. Π§Ρ‚ΠΎΠ±Ρ‹ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΠΈΠ»ΠΈ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ своими собствСнными ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΌΠΈ, установитС свойство converters. ЗначСния свойств ΠΌΠΎΠ³ΡƒΡ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ любой ΠΈΠ· интСрфСйсов Converter, ConverterFactory ΠΈΠ»ΠΈ GenericConverter.

<bean id="conversionService"
        class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="example.MyCustomConverter"/>
        </set>
    </property>
</bean>

Π’Π°ΠΊΠΆΠ΅ Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ Π½Π° Spring MVC часто ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ConversionService.

Π’ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ситуациях ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π²ΠΎ врСмя прСобразования.

ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ΅ использованиС ConversionService

Π§Ρ‚ΠΎΠ±Ρ‹ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с экзСмпляром ConversionService ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Π½Π΅Π΄Ρ€ΠΈΡ‚ΡŒ ссылку Π½Π° Π½Π΅Π³ΠΎ, ΠΊΠ°ΠΊ это дСлаСтся для любого Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ Π±ΠΈΠ½Π°. Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ, ΠΊΠ°ΠΊ это ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ:

Java
@Service
public class MyService {
    public MyService(ConversionService conversionService) {
        this.conversionService = conversionService;
    }
    public void doIt() {
        this.conversionService.convert(...)
    }
}
Kotlin
@Service
class MyService(private val conversionService: ConversionService) {
    fun doIt() {
        conversionService.convert(...)
    }
}

Для Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π° случаСв использования ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ convert, ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ targetType, Π½ΠΎ ΠΎΠ½ Π½Π΅ сработаСт с Π±ΠΎΠ»Π΅Π΅ слоТными Ρ‚ΠΈΠΏΠ°ΠΌΠΈ, Ρ‚Π°ΠΊΠΈΠΌΠΈ ΠΊΠ°ΠΊ коллСкция ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΠ·ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ элСмСнта. НапримСр, Ссли Π²Π°ΠΌ потрСбуСтся ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ List Ρ‚ΠΈΠΏΠ° Integer Π² List Ρ‚ΠΈΠΏΠ° String, Ρ‚ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Ρ„ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ исходного ΠΈ Ρ†Π΅Π»Π΅Π²ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠΎΠ².

К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, TypeDescriptor прСдоставляСт Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΎΠΏΡ†ΠΈΠΈ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠ΅ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это Ρ‚Π°ΠΊ ΠΆΠ΅ просто, ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅:

Java
DefaultConversionService cs = new DefaultConversionService();
List<Integer> input = ...
cs.convert(input,
    TypeDescriptor.forObject(input), // ДСскриптор Ρ‚ΠΈΠΏΠ° List<Integer>
    TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class)));
Kotlin
val cs = DefaultConversionService()
val input: List<Integer> = ...
cs.convert(input,
        TypeDescriptor.forObject(input), // ДСскриптор Ρ‚ΠΈΠΏΠ° List<Integer>
        TypeDescriptor.collection(List::class.java, TypeDescriptor.valueOf(String::class.java)))

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ DefaultConversionService автоматичСски рСгистрируСт ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ подходят для Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π° срСд. К Π½ΠΈΠΌ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΉ, скалярныС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ ΠΈ Π±Π°Π·ΠΎΠ²Ρ‹Π΅ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ Object-to-String. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π·Π°Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π΅ ΠΆΠ΅ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ Π² любом ConverterRegistry с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ статичСского ΠΌΠ΅Ρ‚ΠΎΠ΄Π° addDefaultConverters класса DefaultConversionService.

ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ для Ρ‚ΠΈΠΏΠΎΠ² Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ для массивов ΠΈ ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΉ, поэтому Π½Π΅Ρ‚ нСобходимости ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ спСциализированный ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ для прСобразования ΠΈΠ· Collection Ρ‚ΠΈΠΏΠ° S Π² Collection Ρ‚ΠΈΠΏΠ° T, Ссли ΠΈΡΡ…ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΈΠ· Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ стандартная ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΊΠΎΠ»Π»Π΅ΠΊΡ†ΠΈΠΉ Π±ΡƒΠ΄Π΅Ρ‚ умСстной.

ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ
  • популярныС
  • Π½ΠΎΠ²Ρ‹Π΅
  • старыС
Для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ Π’Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ
Π£ этой страницы Π΅Ρ‰Π΅ Π½Π΅Ρ‚ Π½ΠΈ ΠΎΠ΄Π½ΠΎΠ³ΠΎ коммСнтария