用来记录一些原创性的总结
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()
方法的实现为a
与b
相等时则相乘,否则就相加,则我们可以针对该方法提供一个对应的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
来替换beanA
的add()
方法实现,这是通过replaced-method
元素来指定的。其需要指定两个属性,name
和replacer
。name
用来指定需要替换的方法的名称,而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所写)