您的位置:首页 > 编程语言 > Java开发

Spring之不同步的Bean

2016-02-28 23:42 477 查看
singleton作用域的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行为。



为了解决这样的问题,我们利用方法注入,方法注入通常使用lookup方法注入,使用lookup方法注入可以让Spring容器重写容器中Bean的抽象或具体方法,返回查找容器中其他Bean的结果,被查找的Bean通常是一个non-singleton Bean(尽管也可以是一个singleton的)。Spring通过使用JSK动态代理或cglib库修改客户的二进制码,从而实现上述要求。下面我们来看一个例子。

1) 将调用者Bean的实现类定义为抽象类,并定义一个抽象方法来获取被依赖的Bean.

public abstract class Chinese implements Person
{
private Dog dog;
// 定义抽象方法,该方法用于获取被依赖Bean
public abstract Dog getDog();
public void hunt()
{
System.out.println("我带着:" + getDog() + "出去打猎");
System.out.println(getDog().run());
}
}

2) 在<bean../>元素中添加<lookup-method../>子元素让Spring为调用者Bean的实现类实现指定的抽象方法。Spring为抽象方法提供实现体之后,这个方法就会变成具体方法,这个类也就变成了具体类,拉下来Spring就可以创建该Bean的实例。<lookup-method../>元素需要指定如下两个属性。

Ø name:指定需要让Spring实现的方法

Ø bean:指定Spring实现该方法的返回值

<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="chinese" class="com.owen.app.service.impl.Chinese">
<!-- Spring只要检测到lookup-method元素,
Spring会自动为该元素的name属性所指定的方法提供实现体。-->
<lookup-method name="getDog" bean="gunDog"/>
</bean>
<!-- 指定gunDog Bean的作用域为prototype,
希望程序每次使用该Bean时用到的总是不同的实例 -->
<bean id="gunDog" class="com.owen.app.service.impl.GunDog"
scope="prototype">
<property name="name" value="旺财"/>
</bean>
</beans>


3) 下面定一个测试类。

public class SpringTest
{
public static void main(String[] args)
{
// 以类加载路径下的beans.xml作为配置文件,创建Spring容器
ApplicationContext ctx = new
ClassPathXmlApplicationContext("beans.xml");
Person p1 = ctx.getBean("chinese" , Person.class);
Person p2 = ctx.getBean("chinese" , Person.class);
// 由于chinese Bean是singleton行为,
// 因此程序两次获取的chinese Bean是同一个实例。
System.out.println(p1 == p2);
p1.hunt();
p2.hunt();
}
}

4) 测试结果。

true

我带着:com.owen.app.service.impl.GunDog@4b553d26出去打猎

我是一只叫旺财的猎犬,奔跑迅速…

我带着:com.owen.app.service.impl.GunDog@69a3d1d出去打猎

我是一只叫旺财的猎犬,奔跑迅速…
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: