Spring的方法注入可分為兩種
- 查找方法注入:用于注入方法返回結(jié)果,也就是說(shuō)能通過(guò)配置方式替換方法返回結(jié)果。即我們通常所說(shuō)的lookup-method注入。
- 替換方法注入:可以實(shí)現(xiàn)方法主體或返回結(jié)果的替換,即我們通常所說(shuō)的replaced-method注入。
1. lookup-method注入
單例模式的bean只會(huì)被創(chuàng)建一次,IoC容器會(huì)緩存該bean實(shí)例以供下次使用;原型模式的bean每次都會(huì)創(chuàng)建一個(gè)全新的bean,IoC容器不會(huì)緩存該bean的實(shí)例。那么如果現(xiàn)在有一個(gè)單例模式的bean引用了一個(gè)原型模式的bean呢?如果無(wú)特殊處理,則被引用的原型模式的bean也會(huì)被緩存,這就違背了原型模式的初衷,這時(shí)使用lookup-method注入可以解決該問(wèn)題。
- bean
package com.lyc.cn.v2.day01.method.lookupMethod;
/**
* @author: LiYanChao
* @create: 2018-09-05 15:10
*/
public abstract class Car {
//用于lookup-method注入
public abstract Taxi createTaxi();
private Taxi taxi;
public Taxi getTaxi() {
return taxi;
}
//setter注入
public void setTaxi(Taxi taxi) {
this.taxi = taxi;
}
}
package com.lyc.cn.v2.day01.method.lookupMethod;
/**
* @author: LiYanChao
* @create: 2018-09-05 15:10
*/
public class Taxi {
public void say() {
System.out.println("I am a Taxi...");
}
}
- xml
<!-- ====================lookup-method屬性注入==================== -->
<bean id="car" class="com.lyc.cn.v2.day01.method.lookupMethod.Car">
<!--注意:下面這句配置和lookup-method注入沒(méi)有關(guān)系,我們只是為了出于演示和說(shuō)明配置該bean-->
<property name="taxi" ref="taxi"/>
<!--lookup-method注入-->
<lookup-method name="createTaxi" bean="taxi"/>
</bean>
<bean id="taxi" class="com.lyc.cn.v2.day01.method.lookupMethod.Taxi" scope="prototype"/>
<!-- ====================replace-method屬性注入==================== -->
<bean id="dogReplaceMethod" class="com.lyc.cn.v2.day01.method.replaceMethod.ReplaceDog"/>
<bean id="originalDogReplaceMethod" class="com.lyc.cn.v2.day01.method.replaceMethod.OriginalDog">
<replaced-method name="sayHello" replacer="dogReplaceMethod">
<arg-type match="java.lang.String"></arg-type>
</replaced-method>
</bean>
- 測(cè)試
@Test
public void test8() {
// 測(cè)試lookup-method注入
Car car1 = xmlBeanFactory.getBean("car", Car.class);
Car car2 = xmlBeanFactory.getBean("car", Car.class);
System.out.println("Car:singleton,所以animal1==animal2應(yīng)該為" + (car1 == car2));
Taxi dog1 = car1.getTaxi();
Taxi dog2 = car2.getTaxi();
System.out.println("Taxi:prototype,Car:singleton,未使用lookup-method注入所以dog1==dog2應(yīng)該為" + (dog1 == dog2));
//注意:這里是通過(guò)createDog()方法獲取
Taxi taxi3 = car1.createTaxi();
Taxi taxi4 = car2.createTaxi();
System.out.println("Taxi:prototype,Car:singleton,使用了lookup-method注入所以dog3==dog4應(yīng)該為" + (taxi3 == taxi4));
}
- 結(jié)果
========測(cè)試方法開(kāi)始=======
Car:singleton,所以animal1==animal2應(yīng)該為true
Taxi:prototype,Car:singleton,未使用lookup-method注入所以dog1==dog2應(yīng)該為true
Taxi:prototype,Car:singleton,使用了lookup-method注入所以dog3==dog4應(yīng)該為false
========測(cè)試方法結(jié)束=======
- 分析
未使用lookup-method注入時(shí),通過(guò)Car的實(shí)例獲取的Taxi實(shí)例是被緩存的(配置文件中Taxi的scope="prototype");而使用了lookup-method注入時(shí),通過(guò)Car的實(shí)例獲取的Taxi實(shí)例則是每次都是新建的,不是被緩存的,這也就達(dá)到了我們的目的。
2. replaced-method注入
主要作用就是替換方法體及其返回值,其實(shí)現(xiàn)也比較簡(jiǎn)單
- bean
package com.lyc.cn.v2.day01.method.replaceMethod;
/**
* @author: LiYanChao
* @create: 2018-09-06 00:01
*/
public class OriginalDog {
public void sayHello() {
System.out.println("Hello,I am a black dog...");
}
public void sayHello(String name) {
System.out.println("Hello,I am a black dog, my name is " + name);
}
}
package com.lyc.cn.v2.day01.method.replaceMethod;
import org.springframework.beans.factory.support.MethodReplacer;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* @author: LiYanChao
* @create: 2018-09-06 00:02
*/
public class ReplaceDog implements MethodReplacer {
@Override
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
System.out.println("Hello, I am a white dog...");
Arrays.stream(args).forEach(str -> System.out.println("參數(shù):" + str));
return obj;
}
}
replace-method注入需實(shí)現(xiàn)MethodReplacer接口,并重寫(xiě)reimplement方法。
- xml
<!-- ====================replace-method屬性注入==================== -->
<bean id="dogReplaceMethod" class="com.lyc.cn.v2.day01.method.replaceMethod.ReplaceDog"/>
<bean id="originalDogReplaceMethod" class="com.lyc.cn.v2.day01.method.replaceMethod.OriginalDog">
<replaced-method name="sayHello" replacer="dogReplaceMethod">
<arg-type match="java.lang.String"></arg-type>
</replaced-method>
</bean>
- 測(cè)試
@Test
public void test9() {
//測(cè)試replace-method注入
OriginalDog originalDog = xmlBeanFactory.getBean("originalDogReplaceMethod", OriginalDog.class);
originalDog.sayHello("輸出結(jié)果已經(jīng)被替換了。。。");
}
- 結(jié)果
========測(cè)試方法開(kāi)始=======
Hello, I am a white dog...
參數(shù):輸出結(jié)果已經(jīng)被替換了。。。
========測(cè)試方法結(jié)束=======
- 分析
OriginalDog類的sayHello方法輸出的是Hello,I am a black dog, my name is xxx,但是通過(guò)replace-method注入,成功的將其替換成reimplement方法。
本節(jié)的內(nèi)容基于配置,只要了解如何配置,就可以正常使用了,不在做過(guò)多的分析。