欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring 单例模式bean 中引用原型模式bean的一些考虑

程序员文章站 2022-06-03 18:59:56
...

一、bean的作用域

众所周知Spring bean的作用范围取值有五种(scope属性控制):

singleton:单例,也是默认值

prototype: 多例,比如让Spring接管struts2的action的时候就必须配置此属性

request: 一次请求以及此次请求的转发

session: 作用范围是一次会话

globalsession: 作用范围是一次全局绘画,比如多台服务器之间需要共用同一个bean的时候就需要此属性。

二、单例的bean引用原型模式的bean

SingletonA 的代码如下

@Service
public class SingletonA {

    @Autowired
    private PrototypeB prototypeB;

    public void printlnB(){
        System.out.println(prototypeB);
    }
}

PrototypeB代码如下

@Service
@Scope(value = "prototype")
public class PrototypeB {

}

测试类

public class SpringTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        applicationContext.getBean(SingletonA.class).printlnB();
        applicationContext.getBean(SingletonA.class).printlnB();
        applicationContext.getBean(SingletonA.class).printlnB();
    }
}

结果:

[email protected]
[email protected]
[email protected]

这是应该很容易理解,因为SingletonA是单例的,在整个Spring容器里面只会创建一次,在创建的时候给的prototypeB是什么就是什么了。那么问题来了,假如在某些场景下,SingletonA中用到prototypeB的时候,都是要新的,而不是都是同一个。

方法一:在SingletonA注入ApplicationContext,具体实现如下

@Service
public class SingletonA {

    @Autowired
    private PrototypeB prototypeB;

    @Autowired
    private ApplicationContext applicationContext;

    public void printlnB(){
        prototypeB = applicationContext.getBean(PrototypeB.class);
        System.out.println(prototypeB);
    }
}

方法二:SingletonA实现ApplicationContextAware接口

@Service
public class SingletonA implements ApplicationContextAware {

    @Autowired
    private PrototypeB prototypeB;

    private ApplicationContext applicationContext;

    public void printlnB(){
        prototypeB = applicationContext.getBean(PrototypeB.class);
        System.out.println(prototypeB);
    }

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

方法三:使用Lookup注解

@Service
public  class SingletonA {

    @Lookup
    protected  PrototypeB createPrototypeB(){
        return null;
    };

    public void printlnB(){
        PrototypeB prototypeB = createPrototypeB();
        System.out.println(prototypeB);
    }
}

官网上面也有详细的讲解 1.4.6 Lookup Method Injection,地址如下

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-method-injection