Spring:协调作用域不同步的Bean
2016-06-07 00:10
429 查看
在整理之前,我们首先应该了解Spring支持的五种作用域:
singleton:单例模式,singleton作用域下的Bean将只产生一个实例,因此我们每次获取的实例都是同一实例。
prototype:每次通过getBean()方法获取Bean实例时,都会产生一个新的Bean实例,因此每次的实例都不同
request:用于Web应用,对于一次Http请求,request作用域内的Bean只生成一个Bean,也就是说同一次请求内,每次获取该Bean,
获取的都是同一实例,但是如果到了下次请求(刷新页面)就会再次产生一个Bean实例,但是在每次的请求内多次获取
Bean实例都是同一实例。
session:对于一次http会话,session作用域的Bean将只生成一个实例,仅在Web应用中该作用域才会真的有效。
global session:每个全局的HttpSession对应一个实例
如果不单独在配置文件中设置,默认的作用域为singleton作用域。
如果对Bean的作用域还不是很了解的可以参考此篇博文:http://blog.csdn.net/vipmao/article/details/51565448
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我们已经知道,singleton是单例模式,该作用域下只产生一个Bean实例,因此我们每次访问所获取的都是同一个实例,但是prototype作用域下的Bean,每次访问都会产生一个新的实例,但是我们试想这么一个情况:当singleton作用域下的Bean依赖一个prototype作用域下的Bean,这就有意思了,在这种情况下,Spring容器会先创建被依赖的prototype作用域的Bean,然后再创建singleton作用域下的主Bean,然后将prototype Bean注入给singleton Bean完成依赖关系,但是singleton
Bean只会创建一次,他的依赖关系也是在创建过程阶段完成的,因此只会完成一次依赖关系的创建,这就导致了每次我们通过singleton Bean访问prototype Bean时,永远访问的只是同一个prototype Bean实例,这样prototype作用域也就丧失了自己原本的作用。
如以下这个例子:
配置文件中我们将gunDog设置成prototype作用股的Bean,并通过普通的依赖注入将prototype Bean注入给singleton Bean
主程序中,我们分两次获取了singleton Bean 并判断是不是同一实例,并分别输出两次的hunt()方法,来看看通过singleton Bean访问prototype Bean是不是也是同一prototype实例
![](http://img.blog.csdn.net/20160606225958533?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
从结果可以看出,两次获取的singleton Bean是同一实例,但是获取的prototype Bean实例也是同一实例,但是按照常理来讲prototype应该是获取一次创建一个实例啊,这样就是去了prototype的作用。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
为了协调作用域不同步的Bean,Spring提供了lookup方法注入,为了使用lookup方法注入,需要如下两步
1:将调用者的Bean实现类定义为抽象类,并定义一个抽象方法来获取被依赖的Bean
2:在<bean>元素中添加<lookup-method>子元素让Spring为调用者Bean的实现类实现指定的抽象方法,
添加<lookup-method>子元素后,<lookup-method>子元素告诉Spring需要实现哪个抽象方法,Spring为抽象方法提供实现体以后,这个方法就会变成具体类,下面Spring就可以创建该Bean的实例了。
使<lookup-method>元素要制定如下两个属性
1:name:告诉Spring需要实现哪个抽象方法
2:bean:指定Spring实现该方法后的返回值
上面在定义Chinese Bean的时候,添加了<lookup-method>子元素,该元素内有name、bean属性,就是说Spring应负责实现getDog()方法,该方法的返回值是容器中的gunDog Bean实例。并且我们将gunDog Bean作用域设置成prototype
主函数分两次获取了singleton Bean,并通过hun()t两次访问prototype Bean
![](http://img.blog.csdn.net/20160606235807415?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
可以看出,两次访问的prototype是两个不同的实例。
使用lookup方法注入后,系统每次调用getDog()方法都会获得新的gunDog 实例,这就保证当singleton作用域Bean需要prototype Bean时,直接调用GetDog方法即可获得全新实例。这也正是lookup方法注入和普通方法注入的区别
singleton:单例模式,singleton作用域下的Bean将只产生一个实例,因此我们每次获取的实例都是同一实例。
prototype:每次通过getBean()方法获取Bean实例时,都会产生一个新的Bean实例,因此每次的实例都不同
request:用于Web应用,对于一次Http请求,request作用域内的Bean只生成一个Bean,也就是说同一次请求内,每次获取该Bean,
获取的都是同一实例,但是如果到了下次请求(刷新页面)就会再次产生一个Bean实例,但是在每次的请求内多次获取
Bean实例都是同一实例。
session:对于一次http会话,session作用域的Bean将只生成一个实例,仅在Web应用中该作用域才会真的有效。
global session:每个全局的HttpSession对应一个实例
如果不单独在配置文件中设置,默认的作用域为singleton作用域。
如果对Bean的作用域还不是很了解的可以参考此篇博文:http://blog.csdn.net/vipmao/article/details/51565448
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一:普通方法注入
我们已经知道,singleton是单例模式,该作用域下只产生一个Bean实例,因此我们每次访问所获取的都是同一个实例,但是prototype作用域下的Bean,每次访问都会产生一个新的实例,但是我们试想这么一个情况:当singleton作用域下的Bean依赖一个prototype作用域下的Bean,这就有意思了,在这种情况下,Spring容器会先创建被依赖的prototype作用域的Bean,然后再创建singleton作用域下的主Bean,然后将prototype Bean注入给singleton Bean完成依赖关系,但是singletonBean只会创建一次,他的依赖关系也是在创建过程阶段完成的,因此只会完成一次依赖关系的创建,这就导致了每次我们通过singleton Bean访问prototype Bean时,永远访问的只是同一个prototype Bean实例,这样prototype作用域也就丧失了自己原本的作用。
如以下这个例子:
1:chinese Bean实现类
package com.mao.lookup_method; public class Chinese implements Person { private Dog dog; public void setDog(Dog dog) { this.dog = dog; } public Dog getDog() { return dog; } @Override public void hunt() { // TODO Auto-generated method stub System.out.println("我带着"+getDog()+"出去打猎"); System.out.println(getDog().run()); } }上面Chinese Bean包含一个hunt()方法,该方法的执行需要依赖Dog的 方法。这里的Dog是一个接口,我们期望每次执行hunt()方法时可以获得不同的gunDog Bean,所以后面我们在配置文件beans.xml将gunDog Bean设置成prototype作用域。
2:gunDog Bean的实现类 该类实现Dog接口
package com.mao.lookup_method; public class GunDog implements Dog { private String name; public GunDog() { } public void setName(String name) { this.name = name; } @Override public String run() { return"我是一个叫"+name+"的猎犬,奔跑迅速》》》》" ; } }
3:配置文件 beans.xml 配置Bean部分
<bean id="ch" class="com.mao.lookup_method.Chinese"> <!-- Spring只要检测到lookup-method元素,Spring会自动为该元素的name属性数指定的方法提供实现体 --> <!-- 方法的返回值就是bean属性指定的值 --> <property name="dog" ref="gunDog"></property> </bean> <bean id="gunDog" class="com.mao.lookup_method.GunDog" scope="prototype"> <property name="name" value="旺财"></property> </bean>
配置文件中我们将gunDog设置成prototype作用股的Bean,并通过普通的依赖注入将prototype Bean注入给singleton Bean
4:测试程序
package com.mao.lookup_method; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[]args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); Chinese ch1=(Chinese) ctx.getBean("ch"); Chinese ch2=(Chinese) ctx.getBean("ch"); System.out.println(ch2==ch2); ch1.hunt(); ch2.hunt(); } }
主程序中,我们分两次获取了singleton Bean 并判断是不是同一实例,并分别输出两次的hunt()方法,来看看通过singleton Bean访问prototype Bean是不是也是同一prototype实例
5:输出结果
从结果可以看出,两次获取的singleton Bean是同一实例,但是获取的prototype Bean实例也是同一实例,但是按照常理来讲prototype应该是获取一次创建一个实例啊,这样就是去了prototype的作用。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
二:lookup方法注入
为了协调作用域不同步的Bean,Spring提供了lookup方法注入,为了使用lookup方法注入,需要如下两步1:将调用者的Bean实现类定义为抽象类,并定义一个抽象方法来获取被依赖的Bean
2:在<bean>元素中添加<lookup-method>子元素让Spring为调用者Bean的实现类实现指定的抽象方法,
添加<lookup-method>子元素后,<lookup-method>子元素告诉Spring需要实现哪个抽象方法,Spring为抽象方法提供实现体以后,这个方法就会变成具体类,下面Spring就可以创建该Bean的实例了。
使<lookup-method>元素要制定如下两个属性
1:name:告诉Spring需要实现哪个抽象方法
2:bean:指定Spring实现该方法后的返回值
下面是协调作用域不同步Bean的例子,我们将上面的例子稍作修改
1:首先将调用者chinese Bean定义为抽象类,并定义抽象方法获取依赖Bean
package com.mao.lookup_method; public abstract class Chinese implements Person { private Dog dog; //定义抽象方法,该方法用于获取被依赖的Bean public abstract Dog getDog(); @Override public void hunt() { // TODO Auto-generated method stub System.out.println("我带着"+getDog()+"出去打猎"); System.out.println(getDog().run()); } }上面我们将调用者Chinese Bean定义为抽象类,并定义抽象方法getDog()用于获取被依赖Bean ,该方法返回的是被依赖Bean的实例,这里返回的就是gunDog Bean实例,该方法由Spring容器自动调用,然后我们再多次调用hunt()方法从singleton Bean获取prototype Bean,看看是不是获取的还是同一prototype Bean实例。
2:被依赖的gunDog Bean
package com.mao.lookup_method; public class GunDog implements Dog { private String name; public GunDog() { } public void setName(String name) { this.name = name; } @Override public String run() { return"我是一个叫"+name+"的猎犬,奔跑迅速》》》》" ; } }
3:配置文件 beans.aml
<bean id="ch" class="com.mao.lookup_method.Chinese"> <!-- Spring只要检测到lookup-method元素,Spring会自动为该元素的name属性数指定的方法提供实现体 --> <!-- 方法的返回值就是bean属性指定的值 --> <lookup-method name="getDog" bean="gunDog"/> </bean> <bean id="gunDog" class="com.mao.lookup_method.GunDog" scope="prototype"> <property name="name" value="旺财"></property> </bean>
上面在定义Chinese Bean的时候,添加了<lookup-method>子元素,该元素内有name、bean属性,就是说Spring应负责实现getDog()方法,该方法的返回值是容器中的gunDog Bean实例。并且我们将gunDog Bean作用域设置成prototype
4:测试函数 Test.java
package com.mao.lookup_method; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[]args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml"); Chinese ch1=(Chinese) ctx.getBean("ch"); Chinese ch2=(Chinese) ctx.getBean("ch"); System.out.println(ch2==ch2); ch1.hunt(); ch2.hunt(); } }
主函数分两次获取了singleton Bean,并通过hun()t两次访问prototype Bean
5:运行结果
可以看出,两次访问的prototype是两个不同的实例。
使用lookup方法注入后,系统每次调用getDog()方法都会获得新的gunDog 实例,这就保证当singleton作用域Bean需要prototype Bean时,直接调用GetDog方法即可获得全新实例。这也正是lookup方法注入和普通方法注入的区别
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring AOP动态代理-切面
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- 模拟Spring的简单实现
- Spring整合WebSocket应用示例(上)
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- springmvc 发送ajax出现中文乱码的解决方法汇总
- SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
- 详解Java的MyBatis框架和Spring框架的整合运用
- struts2 spring整合fieldError问题
- spring的jdbctemplate的crud的基类dao
- 读取spring配置文件的方法(spring读取资源文件)
- Spring Bean基本管理实例详解