034协调作用域不同的Bean

如果一个singleton Bean 引用了一个 prototype Bean(或者说把一个prototype Bean注入到singleton Bean中),那么就会产生一个问题:

singleton Bean在被预初始化后,接下来singleton Bean中的singleton Bean都是同一个对象,也 就意味着singleton Bean中的 prototype Bean一直都是最开始的那一个。那么就违背了prototype Bean的设计初衷(既然把它设计成prototype 作用域,肯定是想每次用到的bean都是一个全新的bean对象)

解决这个问题有两种方案:
方案一: 放弃一依赖注入,改用在singleton Bean中手动获取prototype Bean对象,并且每次获取Bean对象都要返回全新的Bean。

栗子:

public class Person implements ApplicationContextAware
{
    private ApplicationContext ctx;
    public Dog getDog()
    {
        return ctx.getBean("dog",Dog.class);
    }
    public void hunt()
    {
    	//每次都得到一个全新的狗
        System.out.println("带着" + getDog() + "去打猎!");
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx = applicationContext;
    }
}

public class GunDog implements Dog
{
    private String name;
	//省略getter和setter方法
}

<bean id="person" class="com.lyx.service.Person" />

<bean id="dog" class="com.lyx.service.GunDog" scope="prototype">
  	<property name="name" value="猎狗旺财"/>
</bean>
public class DriverJava
{
    public static void main(String[] args)
    {
        var ctx = new ClassPathXmlApplicationContext("beans.xml");
        Person p = ctx.getBean("person",Person.class);
        Person p2 = ctx.getBean("person",Person.class);
        p.hunt();//带着com.lyx.service.GunDog@2ccca26f去打猎!
        p2.hunt();//带着com.lyx.service.GunDog@66b7550d去打猎!
    }
}

方案二:
上面的过程有些复杂,Spirng用lookup-method标签大大简化了代码
此时用于注入bean的方法(本例中的:Dog getDog())直接写成抽象方法,其他的交割Spirng来完成,当然了需要指定注入的bean,用lookup-method:
lookup-method中有两个属性
name: 指定注入bean的方法的方法名
bean: 指定注入的bean对象

栗子:

public abstract class Person
{
    private ApplicationContext ctx;
    public abstract Dog getDog();
    public void hunt()
    {
    	//每次都得到一个全新的狗
        System.out.println("带着" + getDog() + "去打猎!");
    }
}

public class GunDog implements Dog
{
    private String name;
	//省略getter和setter方法
}

<bean id="person" class="com.lyx.service.Person" >
 	<lookup-method name="getDog" bean="dog"/>
</bean>

<bean id="dog" class="com.lyx.service.GunDog" scope="prototype">
    <property name="name" value="猎狗旺财"/>
</bean>

第二种方案明显简便很多,而且避免的代码污染。
其实方案二原理和方案一类似,只不过这些繁琐的操作Spirng在底层利用动态代理帮我们完成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值