Spring中lookup方法简单介绍(协调作用域不同步的Bean)

问题场景:

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
  • 在<bean.../>元素中添加<looup-method.../>子元素,让Spring为调用者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

<?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.xsd">
    <bean id="hunt" class="example.Hunter" >
        <lookup-method  name="getDog" bean="gundog"/>
    </bean>
    <bean id="gundog" class="example.Dog" scope="prototype">
        <property name="name" value="旺财"/>
    </bean>


</beans>

测试:

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作用域的 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值