Elim的博客

用来记录一些原创性的总结


Elim

8方法注入之替换方法实现

Spring提供了一种替换方法实现的机制,可以让我们改变某个bean某方法的实现。打个比方我们有一个bean,其中拥有一个add()方法可以用来计算两个整数的和,但这个时候我们想把它的实现逻辑改为如果两个整数的值相同则把它们相乘,否则还是把它们相加,在不改变或者是不能改变源码的情况下我们就可以通过Spring提供的替换方法实现机制来实现这一要求。

替换方法实现机制的核心是MethodReplacer接口,其中定义了一个reimplement ()方法,我们的替换方法实现的主要逻辑就是在该方法中实现的,具体定义如下:

public interface MethodReplacer {

	/**
	 * Reimplement the given method.
	 * @param obj the instance we're reimplementing the method for
	 * @param method the method to reimplement
	 * @param args arguments to the method
	 * @return return value for the method
	 */
	Object reimplement(Object obj, Method method, Object[] args) throws Throwable;

}

我们可以看到reimplement()方法将接收三个参数,其中obj表示需要替换方法实现的bean对象,method需要替换的方法,args则表示对应的方法参数。针对前面打的比方,假设我们有如下这样一个类定义对应的bean

public class BeanA {

	public int add(int a, int b) {
		return a+b;
	}
	
}
	<bean id="beanA" class="com.app.BeanA"/>

如果我们需要替换add()方法的实现为ab相等时则相乘,否则就相加,则我们可以针对该方法提供一个对应的MethodReplacer的实现类,具体实现如下所示。

public class BeanAReplacer implements MethodReplacer {

	/**
	 * @param obj 对应目标对象,即beanA
	 * @param method 对应目标方法,即add
	 * @param args 对应目标参数,即a和b
	 */
	public Object reimplement(Object obj, Method method, Object[] args)
			throws Throwable {
		Integer a = (Integer)args[0];
		Integer b = (Integer)args[1];
		if (a.equals(b)) {
			return a * b;
		} else {
			return a + b;
		}
	}

}

之后就需要在定义beanA时指定使用BeanAReplacer来替换beanAadd()方法实现,这是通过replaced-method元素来指定的。其需要指定两个属性,namereplacername用来指定需要替换的方法的名称,而replacer则用来指定用来替换的MethodReplacer对应的bean。所以,此时我们的beanA应该如下定义:

	<bean id="beanAReplacer" class="com.app.BeanAReplacer"/>
	<bean id="beanA" class="com.app.BeanA">
		<replaced-method name="add" replacer="beanAReplacer"/>
	</bean>

如果我们的MethodReplacer将要替换的方法在对应的bean中属于重载类型的方法,即存在多个方法名相同的方法时,我们还需要通过在replaced-method元素下通过arg-type元素来定义对应方法参数的类型,这样就可以区分需要替换的是哪一个方法。所以,针对上述示例,我们也可以如下定义:

	<bean id="beanAReplacer" class="com.app.BeanAReplacer"/>
	<bean id="beanA" class="com.app.BeanA">
		<replaced-method name="add" replacer="beanAReplacer">
			<arg-type match="int"/>
			<arg-type match="int"/>
		</replaced-method>
	</bean>

对应方法名的方法只存在一个时,arg-type将不起作用,即Spring此时不会根据arg-type去取对应的方法进行替换,或者换句话说就是当replaced-method指定名称的方法只存在一个时,无论arg-type如何定义都是可以的。

(注:本文是基于Spring4.1.0所写)