Прием внедрения методов позволяет внедрять в компоненты определения целых методов.
Spring предоставляет Java-программистам возможность внедрения методов в Java-классы во время выполнения.
Фреймворк Spring поддерживает две формы внедрения методов:
- замещение метода – позволяет во время выполнения заместить существующий метод (абстрактный или конкретный) новой реализацией;
- внедрение метода чтения – позволяет во время выполнения заместить существующий метод (абстрактный или конкретный) новой реализацией, возвращающей определенный компонент из контекста Spring.
Пример замещения методов
<bean id="magicBox" class="com.springinaction.springidol.MagicBoxImpl">
<replaced-method name="getContents" replacer="tigerReplacer" />
</bean>
<bean id="tigerReplacer" class="com.springinaction.springidol.TigerReplacer" />
Сейчас в компоненте magicBox имеется элемент <replaced-method> . Как следует из названия, этот элемент используется для замены метода новой реализацией. В данном случае атрибут name указывает имя замещаемого метода getContents().
package com.springinaction.springidol;
import java.lang.reflect.Method;
import org.springframework.beans.factory.support.MethodReplacer;
public class TigerReplacer implements MethodReplacer {
public Object reimplement(Object target, Method method, // Подмена
Object[] args) throws Throwable { // метода
return "A ferocious tiger"; // Помещает тигра в ящик
}
}
Класс TigerReplacer реализует интерфейс MethodReplacer, требующий реализации единственного метода reimplement(). Этот метод принимает три аргумента: объект, в котором будет производиться замещение метода, метод, подлежащий замещению, и массив аргументов, принимаемых методом.
Тело метода reimplement() фактически становится новой реализацией метода getContents().
Способ применения:
Прием внедрения метода с успехом может использоваться, когда фактическая реализация замещаемого метода не известна до момента развертывания. К этому моменту класс с замещающей реализацией метода можно оформить в виде JAR-файла и поместить его в библиотеку классов (classpath) приложения.
Пример внедрения метода чтения
Внедрение через метод чтения – это особый случай внедрения методов, когда объявляется метод (обычно абстрактный), возвращающий компонент определенного типа, но фактически возвращаемый компонент определяется в контексте Spring.
<bean id="stevie" class="com.springinaction.springidol.Instrumentalist">
<lookup-method name="getInstrument" bean="guitar" />
<property name="song" value="Greensleeves" />
</bean>
Как и в элементе <replaced-method>, атрибут name элемента <lookup-method> определяет замещаемый метод. Здесь замещается метод getInstrument(). Атрибут bean определяет компонент, возвращаемый методом getInstrument().
Важно помнить, что при использовании элемента <lookup-method> для внедрения метода чтения совсем необязательно, чтобы замещаемый метод был методом чтения (то есть методом, имя которого начинается со слова get). С помощью элемента <lookup-method> можно заместить любой метод, возвращающий некоторое значение.
Следует также отметить, что даже при том, что прием внедрения методов позволяет замещать их реализации, нет никакой возможности изменить сигнатуру метода. Типы параметров и возвращаемого значения должны оставаться такими, какие они есть.
package com.springinaction.springidol;
public abstract class Instrumentalist implements Performer {
public Instrumentalist() {}
public void perform() throws PerformanceException {
System.out.print("Playing " + song + " : ");
getInstrument().play(); // Используется внедряемый метод
} // getInstrument()
private String song;
public void setSong(String song) {
this.song = song;
}
public abstract Instrument getInstrument(); // Внедряемый метод
}
Для поддержки внедрения методов чтения фреймворк Spring предлагает элемент <lookup-method> . Как и <replaced-method>, элемент <lookup-method> замещает существующий метод новой реализацией во время выполнения.
<lookup-method name="getInstrument" bean="guitar" />
<property name="song" value="Greensleeves" />
</bean>
Как и в элементе <replaced-method>, атрибут name элемента <lookup-method> определяет замещаемый метод. Здесь замещается метод getInstrument(). Атрибут bean определяет компонент, возвращаемый методом getInstrument().
Важно помнить, что при использовании элемента <lookup-method> для внедрения метода чтения совсем необязательно, чтобы замещаемый метод был методом чтения (то есть методом, имя которого начинается со слова get). С помощью элемента <lookup-method> можно заместить любой метод, возвращающий некоторое значение.
Следует также отметить, что даже при том, что прием внедрения методов позволяет замещать их реализации, нет никакой возможности изменить сигнатуру метода. Типы параметров и возвращаемого значения должны оставаться такими, какие они есть.