协调作用域不同步的Bean

来源:互联网 发布:淘宝8点上新怎么抢最快 编辑:程序博客网 时间:2024/05/02 02:17

当两个singleton作用域的bean存在依赖关系的时候,或者当prototype作用域的bean依赖singleton作用域的bean时,使用spring提供的依赖注入进行管理即可。

singlteon作用域的bean只有一次初始化的机会,他的依赖关系也只在初始化阶段被设置,当singleton作用域的bean依赖prototype作用域的bean时,Spring容器会在初始化singleton作用域的bean之前,先创建被依赖的prototype bean,然后才初始化singleton bean,并将prototype bean注入singleton bean,这回导致以后无论何时进行singleton bean 去访问prototype bean时,得到的永远是最初那个prototype bean-----这样就相当于singleton bean 把他所依赖的prototype bean变成了singleton行为。

Dog接口

package org.lizengjie.service;public interface Dog {public String run();}

GunDog类:

package org.lizengjie.service;public class GunDog implements Dog{private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public GunDog(){}@Overridepublic String run() {// TODO Auto-generated method stubreturn "我是一只叫"+name+"猎犬";}}


Person接口:

package org.lizengjie.service;public interface Person {public void hunt();}

Chinese类:

package org.lizengjie.service;import org.springframework.beans.factory.BeanNameAware;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;public  class Chinese implements Person{private Dog dog;//public abstract Dog getDog();public Dog getDog() {return dog;}public void setDog(Dog dog) {this.dog = dog;}@Overridepublic void hunt() {// TODO Auto-generated method stubSystem.out.println("我带着:"+getDog()+"出去打猎");System.out.println(getDog().run());}}

beans.xml文件:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">      <bean id="chinese" class="org.lizengjie.service.Chinese">      <property name="dog" ref="gunDog"></property>   </bean>      <bean id="gunDog" class="org.lizengjie.service.GunDog" scope="prototype">       <property name="name" value="旺财"></property>   </bean></beans>

测试类:

package lee;import org.lizengjie.service.Chinese;import org.lizengjie.service.Person;import org.springframework.beans.factory.BeanFactory;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.AbstractApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * @author li * 协调作用域不同步的bean */public class BeanTest {public static void main(String[] args) throws Exception{AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");Chinese c = ctx.getBean("chinese", Chinese.class);c.hunt();c.hunt();}}

运行结果显示:

我带着:org.lizengjie.service.GunDog@18a577d出去打猎我是一只叫旺财猎犬我带着:org.lizengjie.service.GunDog@18a577d出去打猎我是一只叫旺财猎犬
从运行结果上可以看出两次运行的hashcode是一样的。所以将prototype当成了singleton。
问题:singleton作用域的bean依赖于prototype作用域的bean时,会产生不同不步的现象:
解决该问题有如下两种思路:
1 放弃依赖注入:singleton作用域的bean每次需要prototype作用域的bean时,主动向容器请求新的bean实例,即可保证每次注入的prototype bean实例都是最新的实例。
2 利用方法注入。
一般都采用第二种方法:利用方法注入。
为了使用lookup方法注入,大致需要两步:
1 将调用者Bean的实现类定义为抽象类,并定义一个抽象方法来获取被依赖的Bean
2 在<bean/>元素中添加<lookup-method>子元素,让spring为调用者Bean的实现类实现指定的抽象方法。


使用<lookup-method>元素需要指定两个属性:
name:指定需要让spring实现的方法
bean:指定spring实现该方法的返回值

Chinese实现类:



package org.lizengjie.service;import org.springframework.beans.factory.BeanNameAware;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;public abstract class Chinese implements Person{private Dog dog;public abstract Dog getDog();/*public Dog getDog() {return dog;}public void setDog(Dog dog) {this.dog = dog;}*/@Overridepublic void hunt() {// TODO Auto-generated method stubSystem.out.println("我带着:"+getDog()+"出去打猎");System.out.println(getDog().run());}}
   


beans.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">      <!-- <bean id="chinese" class="org.lizengjie.service.Chinese">      <property name="dog" ref="gunDog"></property>   </bean> -->      <bean id="chinese" class="org.lizengjie.service.Chinese">       <lookup-method name="getDog" bean="gunDog"/>   </bean>   <bean id="gunDog" class="org.lizengjie.service.GunDog" scope="prototype">       <property name="name" value="旺财"></property>   </bean></beans>

最后运行结果显示:


我带着:org.lizengjie.service.GunDog@18a577d出去打猎
我是一只叫旺财猎犬
我带着:org.lizengjie.service.GunDog@5ear45ds出去打猎
我是一只叫旺财猎犬


执行结果表明:使用lookup方法注入后,系统每次调用getDog()方法时都将生成一个新的gunDog实例,这就可以保证当singleton作用域的bean需要prototype 作用域的bean实例时,直接调用getDog()方法即可获取全新的实例,从而可避免一直使用最早注入的bean实例。


0 0
原创粉丝点击