在大部分情况下,容器中的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实例。
对于上面的问题Spring提供了三种解决方案:
- 放弃控制反转。通过实现ApplicationContextAware接口让bean A能够感知bean 容器,并且在需要的时候通过使用getBean("B")方式向容器请求一个新的bean B实例。
- Lookup方法注入。Lookup方法注入利用了容器的覆盖受容器管理的bean方法的能力,从而返回指定名字的bean实例。
- 自定义方法的替代方案。该注入能使用bean的另一个方法实现去替换自定义的方法。
这里只说前两种方案的实现,第三种方案因为不常用,略过不提,有兴趣的可以了解一下。
一、通过实现ApplicationContextAware接口以编程的方式实现
ApplicationContextAware和BeanFactoryAware差不多,用法也差不多,实现了ApplicationContextAware接口的对象会拥有一个ApplicationContext的引用,这样我们就可以已编程的方式操作ApplicationContext。看下面的示例:
定义Command接口和其实现类AsyncCommand。
package org.luosijin.springTest.applicationContextAware;
/**
* 一个命令接口
* @author luosijin
*
*/
public interface Command
{
public Object execute();
}
package org.luosijin.springTest.applicationContextAware;
/**
* 一个异步处理命令的实现
* @author luosijin
*
*/
public class AsyncCommand implements Command {
/* (non-Javadoc)
* @see org.luosijin.springTest.applicationContextAware.Command#excute()
*/
@Override
public Object execute() {
//返回自身实例,是为了测试的时候好看出每次返回的不是同一个实例
return this;
}
}
写一个singleton例
package org.luosijin.springTest.applicationContextAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* 命令管理器
* @author luosijin
*
*/
public class CommandManager implements ApplicationContextAware {
//用于保存ApplicationContext的引用,采用set方式注入
private ApplicationContext applicationContext;
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.Appl