去掉对Spring BeanFacotry的getBean步骤的依赖
去掉对Spring BeanFacotry的getBean方法的依赖
在使用Spring时,有时会碰到这种情况:
那么如何解决这个问题呢,一般的做法可能是实现Spring的ApplicationContextAware接口,然后在没个方法中显示地调用ApplicationContext的getBean方法,当然这个Bean在Spring的配置文件中是配置成非Singlton的。如下面代码所示:
上面的代码可以解决我们之前说的问题,但是,这样做就形成了对Spring框架代码的依赖,降低了应用程序代码的可以执行和可重用性。
不过不用担心,Spring已经为我们考虑到了这一点,并且提供了几种更好的解决方案。下面讲一下其中的两种。这两种方法Spring都是通过使用CGLIB自动生成字节码来完成的。
解决方案一:Lookup Method。
仍然以上面的ClazzA为例。这种方法需要将ClazzA定义为抽象类,并在该类中定义一个抽象的createBean方法。修改后的代码如下:
然后在Spring的配置文件中做如下定义:
这样定义之后,Spring就会使用CGLIB自动生成一个实现了createBean方法的ClazzA的一个实现类,并让createBean返回ClazzB。
上面所说的那个createBean方法必须符合下面的方法签名:
详细信息可以参见Spring文档的3.4节。
解决方案二:使用ServiceLocatorFactoryBean。
这种方案交第一种方案更加灵活一点,但是付出的代价是要单独定一个工厂接口。这种方法在Spring的ServiceLocatorFactoryBean类的API文档中有详细介绍,这里就不再累述了。
在使用Spring时,有时会碰到这种情况:
引用
需要在一个类中使用一个非Singlton类型的Bean,比如每次方法调用都需要new一个新的Bean。但是,由于Spring的依赖注入是在Bean初始化完成之后进行的,而且只进行一次,因此就无法在每次方法调用时注入新的Bean。
那么如何解决这个问题呢,一般的做法可能是实现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文档中有详细介绍,这里就不再累述了。