我们通常使用lookup方法注入,它可使Spring替换一个Bean的抽象或具体方法,返回查找容器中,其他Bean的结果,被查找的Bean通常是一个non-singleton Bean。
无状态的Bean的作用域一般可以配置成singleton单实例,如果我们向singleton的BeanA注入prototype的BeanB,并希望每次调用BeanA的getBeanB()时都能返回一个新的BeanB,使用传统的注入方式方法将无法实现这样的要求。因为singleton的Bean注入关联Bean的动作只有一次,虽然BeanB的作用域是prototype类型,返回的对象不是最开始注入的那个bean。
如果希望每次调用BeanA的getBeanB()时都能返回一个新的BeanB一种可选的方案是让Bean实现BeanFactoryAware接口,让BeanA能访问容器的引用,以下代码可以实现方式达到目的:
public class Bean_A implements BeanFactoryAware{
回忆第一篇里讲的Bean的生命周期,当一个Bean的POJO类实现了BeanFactoryAware接口时,当Bean实例化完成并调用setter方法降属性也设置完毕后,会调用BeanFactoryAware接口的setBeanFactory方法,这样我们便可以得到BeanFactory的一个引用。使用BeanFactory我们便可以获取一个全新的scope="prototype" 的Bean实例了。
但是,这种方法,使得一个纯净的POJO类被污染了,因此一般情况下不适用这种方法。
Spring IoC容器有复写Bean方法的能力,这项功能归功于CGLib类包,CGLib可以在运行期动态的操作Class字节码,使Spring替换一个Bean的抽象或具体方法,现在我们将上面的功能使用lookup方法注入来实现:
public class Bean_A{
注意,我们这里的Bean_A是一个纯洁的POJO类。然后在Spring配置文件中为Bean_A添加lookup方法注入,使Spring替换getBean_B() 方法即可。
<bean id="bean_B" class="smzq.Bean_B" scope="prototype"/>
测试:
注:lookup方法还可以为bean动态的创建子类或实现类,现在我们声明一个接口,如下:
public interface BeanInterface {
同样在Spring的配置文件中配置,但这次配置的不是类,而是一个接口。很神奇吧!
<bean id="bean_B" class="smzq.Bean_B" scope="prototype"/>
再测试一下:
由此可见,Spring确实为我们的BaseInter接口创建了实现类。那么这里是抽象类呢?Spring也会为其创建一个子类。
<lookup-method> 元素只有两个属性:
name:指定要让Spring实现的或者替换的方法名称,该方法返回一个Bean对象。
bean:指定name属性指定的方法的返回值。