Method injection(方法注入)
bean都是singleton类型的。如果一个singleton bean要引用另外一个singleton bean,或者一个非singleton bean要引用另外一个非singleton bean时,通常情况下将一个bean定义为另一个bean的property值就可以了。不过对于具有不同生命周期的bean来说这样做就会有问题了,比如在调用一个singleton类型bean A的某个方法时,需要引用另一个非singleton(prototype)类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的的bean B实例。
官方建议:You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it.
借http://blog.csdn.net/zml2004/archive/2006/04/15/664309.aspx例子
Lookup Method Injection
com.spring305.test.methodInjection.RandomT.java
public class RandomT{
private int num = (int)(100*Math.random());
public void printRandom(){
System.out.println("随机数是"+num);
}
}
com.spring305.test.methodInjection.HelloRandom.java
//一个代理接口
public interface HelloRandom {
public RandomT getRandom();
public abstract RandomT createRandom(); // 这个方法最为重要,是方法注入的关键
}
com.spring305.test.methodInjection.HelloAbstract.java
public abstract class HelloAbstract implements HelloRandom {
private RandomT random;
public void setRandom(RandomT random) {
this.random = random;
}
public abstract RandomT createRandom();
@Override
public RandomT getRandom() {
// TODO Auto-generated method stub
return this.random;
}
}
src/methodInjection.xml
Test
//@Test
public void testMethodInjection(){
ApplicationContext context = new ClassPathXmlApplicationContext("methodInjection.xml");
HelloRandom helloRandom1 = (HelloRandom)context.getBean("helloRandom");
System.out.println("下面两个实例没有采用方法注入");
RandomT r1 = helloRandom1.getRandom();
RandomT r2 = helloRandom1.getRandom();
System.out.println("Random 的两个实例是否指向同一个引用:" + (r1 == r2));
r1.printRandom();
r2.printRandom();
System.out.println();
System.out.println("下面两个实例采用方法注入");
HelloRandom helloRandom = (HelloRandom)context.getBean("helloRandom");
RandomT r3 = helloRandom.createRandom();
RandomT r4 = helloRandom.createRandom();
System.out.println("Random 的两个实例是否指向同一个引用:" + (r3 == r4));
r3.printRandom();
r4.printRandom();
}
另官方没有给这种Lookup方法注入而是提供了:Arbitrary method replacement方法替换:
com.spring305.test.methodInjection.MyValueCalculator.java
public class MyValueCalculator {
public String computeValue(String input) {
return input+"_"+(int)(100*Math.random());
}
}
com.spring305.test.methodInjection.ReplacementComputeValue.java
public class ReplacementComputeValue implements MethodReplacer {
@Override
public Object reimplement(Object obj, Method method, Object[] args)
throws Throwable {
String input = (String) args[0];
input += "123";
return input;
}
}
xml中再加上:
String
测试:
@Test
public void testMethod(){
ApplicationContext context = new ClassPathXmlApplicationContext("methodInjection.xml");
ReplacementComputeValue reValue = context.getBean("replacementComputeValue",ReplacementComputeValue.class);
MyValueCalculator myValueCalculator = context.getBean("myValueCalculator",MyValueCalculator.class);
System.out.println(myValueCalculator.computeValue("add"));;
}