Spring中无状态的Bean的作用域一般可配置为单例模式,如果我们往单例模式的A中注入一个prototype的类型B,并希望每次调用getB()时都能返回一个新的B,传统的注入方式就无法达到这样的要求。原因是单例的Bean注入关联Bean的动作只有一次,虽然B的类型是prototype,但每次返回的对象还是最开始的那个B。
为此可以让A实现BeanFactoryAware接口,让A访问容器的引用从而return (B)factory.getBean(“B”);但是这样依赖spring框架接口的设计将与spring框架类绑定在一起。另一种通过方法注入可完美的解决这个问题。
Spring IoC拥有复写Bean方法的能力,这项能力由CGlib包完成。CGlib可以在运行期动态操作Class字节码,为Bean动态创建子类或者实现类。
例如以下的一个接口:
public interface MagicBoss {
Car getCar();
}
不编写任何实现类,仅通过配置为该接口提供动态的实现,让getCar()方法每次都返回一个新的Car Bean:
<bean id="car" class="" p:brand="" scope="prototype"/>
<bean id="magicBoss" class=""/>
<lookup-method name="getCar" bean="car"/>
<bean/>
通过lookup-method元素标签为getCar()提供动态实现,返回prototype的car Bean,Spring将在运行期为MagicBoss接口提供动态实现,效果类似以下代码:
public class MagicBossImpl implements MagicBoss,ApplicationContextAware {
private ApplicationContext ctx;
public Car getCar() {
return (Car)ctx.getCar("car");
}
public void setApplicationContext(ApplicationContext ctx)throws BeansException {
this,ctx = ctx;
}
}
每次调用MagicBoss的getCar()方法时都从容器中获取car Bean,car的作用域为prototype所以每次都返回一个新的car Bean。