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.youkuaiyun.com/zml2004/archive/2006/04/15/664309.aspx例子
Lookup Method Injection
<!--EndFragment-->
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
<!-- 方法注入-->
<bean id="myRandom" class="com.spring305.test.methodInjection.RandomT" scope="prototype" />
<!-- scope="singleton" -->
<bean id="helloRandom" class="com.spring305.test.methodInjection.HelloAbstract" >
<lookup-method name="createRandom" bean="myRandom"/>
<property name="random">
<ref local="myRandom" />
</property>
</bean>
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中再加上:
<bean id="myValueCalculator" class="com.spring305.test.methodInjection.MyValueCalculator"> <!-- arbitrary method replacement --> <replaced-method name="computeValue" replacer="replacementComputeValue"> <arg-type>String</arg-type> </replaced-method> <!-- <replaced-method name="computeValue" replacer="helloReplacer"/> --> </bean> <bean id="replacementComputeValue" class="com.spring305.test.methodInjection.ReplacementComputeValue"/>
测试:
@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"));;
}
本文介绍了Spring框架中的方法注入(Method Injection)与方法替换(Method Replacement)两种高级依赖注入技术。通过实例展示了如何使用lookup-method解决singleton bean调用prototype bean的问题,并通过方法替换实现特定方法的功能增强。
174万+

被折叠的 条评论
为什么被折叠?



