去掉对Spring BeanFacotry的getBean方法的依赖

在使用Spring时,有时会碰到这种情况:
[quote]需要在一个类中使用一个非Singlton类型的Bean,比如每次方法调用都需要new一个新的Bean。但是,由于Spring的依赖注入是在Bean初始化完成之后进行的,而且只进行一次,因此就无法在每次方法调用时注入新的Bean。[/quote]
那么如何解决这个问题呢,一般的做法可能是实现Spring的ApplicationContextAware接口,然后在没个方法中显示地调用ApplicationContext的getBean方法,当然这个Bean在Spring的配置文件中是配置成非Singlton的。如下面代码所示:

public class ClazzA implements ApplicationContextAware{
private ApplicationContext applicationContext;

void setApplicationContext(ApplicationContext applicationContext){
this.applicationContext = applicationContext;
}

public void methodA(){
Object bean = this.applicationContext.getBean("...");
...
}

public void methodB(){
Object bean = this.applicationContext.getBean("...");
...
}

...
}

上面的代码可以解决我们之前说的问题,但是,这样做就形成了对Spring框架代码的依赖,降低了应用程序代码的可以执行和可重用性。
不过不用担心,Spring已经为我们考虑到了这一点,并且提供了几种更好的解决方案。下面讲一下其中的两种。这两种方法Spring都是通过使用CGLIB自动生成字节码来完成的。
解决方案一:Lookup Method。
仍然以上面的ClazzA为例。这种方法需要将ClazzA定义为抽象类,并在该类中定义一个抽象的createBean方法。修改后的代码如下:

public abstract class ClazzA{
public void methodA(){
ClazzB bean = this.applicationContext.getBean("...");
...
}

public void methodB(){
ClazzB bean = this.applicationContext.getBean("...");
...
}

public abstract ClazzB createBean();
...
}

然后在Spring的配置文件中做如下定义:

<bean id="clazzB" class="edu.sjtu.spring.ClazzB" scope="prototype">
<!-- inject dependencies here as required -->
</bean>

<!-- commandProcessor uses statefulCommandHelper -->
<bean id="clazzA" class="edu.sjtu.spring.ClazzA">
<lookup-method name="createBean" bean="command"/>
</bean>

这样定义之后,Spring就会使用CGLIB自动生成一个实现了createBean方法的ClazzA的一个实现类,并让createBean返回ClazzB。
上面所说的那个createBean方法必须符合下面的方法签名:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);


详细信息可以参见Spring文档的3.4节。
解决方案二:使用ServiceLocatorFactoryBean。
这种方案交第一种方案更加灵活一点,但是付出的代价是要单独定一个工厂接口。这种方法在Spring的ServiceLocatorFactoryBean类的API文档中有详细介绍,这里就不再累述了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值