Spring如何在单例的bean中注入多例的bean

在spring中,bean默认是单例的,对于创建一个多例的bean,我们只需要在类上添加Scope注解,并将value指定为`prototype`就行,@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)

@Service
/**
 * 原型模式,每次创建一个bean
 */
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class BService {


    public String testB() {
        return "invoke testB";
    }


}

@Service
public class AService {

    @Autowired
    private BService bService;

    public void testA() {
        // 每次调用时,输出bService的地址,判断是否是不通的实例
        System.out.println(bService);
        String result = bService.testB();
        System.out.println("执行结果:" + result);
    }
}


通过多次执行代码,我们发现,每次输出的bService的地址都是相同

Spring如何在单例的bean中注入多例的bean

那么这个究竟是什么原因呢?在Spring中,由于ASearvice是单例的,只会初始化一次,因此当bService属性被初始化了之后,便不会再改变了。

解决方案

方法一:通过ApplicationContextAware,每次从Spring容器中重新获取BService


@Service
public class AService implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public void testA() {
        // 每次调用时,输出bService的地址,判断是否是不通的实例
        BService bService = getBService();
        System.out.println(bService);
        String result = bService.testB();
        System.out.println("执行结果:" + result);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public BService getBService() {
        return applicationContext.getBean(BService.class);
    }
}


ApplicationContext也可以通过@Autowired注解进行注入

方法二:通过LookUp注解


@Service
public class AService {

    public void testA() {
        // 每次调用时,输出bService的地址,判断是否是不通的实例
        BService bService = getBService();
        System.out.println(bService);
        String result = bService.testB();
        System.out.println("执行结果:" + result);
    }

    @Lookup
    public BService getBService() {
        return null;
    }
}


方法三:对Bservice创建代理类proxyMode = ScopedProxyMode.TARGET_CLASS

11


@Service
/**
 * 原型模式,每次创建一个bean
 */
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class BService {

    public String testB() {
        return "invoke testB";
    }

}

@Service
public class AService {

    @Autowired
    private BService bService;

    public void testA() {
        // 每次调用时,输出bService的地址,判断是否是不通的实例
        System.out.println(bService);
        String result = bService.testB();
        System.out.println("执行结果:" + result);
    }

}


通过@Scope注解,我们为BService创建了一个代理类,这样,每次使用BService时,就会从spring容器中重新获取一个BService

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章