问题场景:
Spring中singleton作用域的Bean只初始化一次,依赖关系也在初始化阶段确定,那么当singleton作用域的Bean依赖prototype作用域的Bean时,问题就来了,Spring在初始化singleton Bean之前,会先创建prototype Bean,最后在初始化singleton Bean的时候将已经创建好的prototype Bean注入进去,这就会导致无论什么时候通过singleton Bean访问prototype Bean时,永远都只访问到最初的那个prototype Bean,这相当于变相的把依赖的prototype Bean变成了singleton Bean。
解决思路:
方法一:放弃依赖注入:singleton作用域的Bean每次需要prototype Bean作用域Bean时,主动项容器请求新的Bean实例,即可保证每次注入的prototype Bean实例都是最新的实例。
方法二:利用方法注入
两种思路分析:
第一种思路虽然可以解决,但是代码主动请求新的Bean实例,将导致程序代码与Spring API耦合,造成代码污染,所以不推荐使用
建议使用第二种方法解决,通常使用 lookup 注入。因为使用lookup方法注入时可以让Spring容器重写容器中Bean的抽象方法或具体方法,返回查找容器中其他Bean的结果。Spring 通过JDK动态代理或cglib库修改客户端的二进制码,从而实现上述要求。
使用lookup方法注入的两个步骤:
将调用者的Bean的实现类定义为抽象类,并定义一个抽象方法来获取被依赖的Bean在
代码实 *** :
场景介绍--Hunter类型的Bean,该Bean包含一个hunt方法,执行该方法需依赖Dog方法---程序要求每次执行hunt方法时都使用不同的Dog Bean,即Dog Bean的作用域是prototype的。
代码:Hunter.java
public abstract class Hunter{ private Dog dog; //定义抽象方法,该方法用于获取被依赖的Bean public abstract Dog getDog(); public void hunt(){ System.out.println("我带着:"+getDog()+"出去打猎了"); System.out.println(getDog().run()); } }
Dog.java
public class Dog { private String name; public void setName(String name) { this.name = name; } public String run(){ return this.name; } }
配置文件:applicationContext.xml
测试:
public class Test { public static void main(String[] args) throws Exception{ //初始化容器 ApplicationContext appcon = new ClassPathXmlApplicationContext("applicationContext.xml"); //获取两次单例bean Hunter h1=appcon.getBean("hunt",Hunter.class); Hunter h2=appcon.getBean("hunt",Hunter.class); //测试两个Bean是否是一个 System.out.println(h1==h2); //分别调用方法 h1.hunt(); h2.hunt(); } }
运行结果截图:
可以看出两次获取的依赖Bean时prototype作用域的
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)