spring非单例模式

spring非单例模式

​ 一般情况下,使用spring的bean都是单例模式的,默认情况下就是如此。单例模式的bean都是无状态的,但是面对复杂场景下,希望bean内能存储状态,这种情况下就不能够使用单例模式了。

spring提供了 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 注解,可以选择是单例模式还是每次使用都创建一个,用法如下。

下面提供的AService作用域是prototype的,其会在每次使用时创建一个新的,Controller1 Controller2内注入的AService是两个不同的示例,AService的构造方法也没调用两次。

1
2
3
4
5
6
7
8
9
@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AService {

public AService() {
System.out.println("AService 被创建");
}

}
1
2
3
4
5
6
7
@Controller
public class Controller1 {

@Resource
AService aService;

}
1
2
3
4
5
6
7
@Controller
public class Controller2 {

@Resource
AService aService;

}

上面是一种场景,他将AService注入不同类时,都创建一个新的实例,但是一旦注入完成后,AService对象就不会再改变了,如果想要方法级别每次使用时都创建一个新的,可以向下面这样做。

做法1,手动获取

这种做法不太好,向类中注入一个BeanFactory,每次方法中使用时,从BeanFactory中获取,因为我们的作用域是原型模式,所以每次获取的都会新建一个,满足我们的要求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Controller
public class Controller1 implements BeanFactoryAware {

BeanFactory beanFactory;

public void doSomething() {
AService aService = beanFactory.getBean(AService.class);
System.out.println(aService);
}

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}

做法2,通过ObjectProvider获取

注入泛型类型为AService的ObjectProvider,想要使用时,调用其getObject()方法,其内部会像上面手动获取一样,从容器中获取,也能满足我们的要求。
此种方式更优雅一点。

1
2
3
4
5
6
7
8
9
10
11
@Controller
public class Controller1 {

@Resource
ObjectProvider<AService> objectProvider;

public void doSomething() {
AService aService = objectProvider.getObject();
System.out.println(aService);
}
}

总结

本文主要想解决的问题是,某个类想要被Spring管理,但又是非单例的,我们如何优雅使用该类。
我们需要了解的是Spring的作用域,他又两种,一种是单例模式,一种是原型模式,原型模式每次从容器中获取时都会创建一个新的实例。
如果只是使用@Resource注入,那么注入后对象就不会再改变,不能实现每次使用都创建新的对象。
我们可以注入BeanFactory每次使用时手动获取来实现目的。
配合ObjectProvider使用,ObjectProvider帮助我们从容器中获取,可以使代码更优雅。


spring非单例模式
https://www.huangchaoyu.com/1947246411.html
作者
hcy
发布于
2021年6月28日
更新于
2024年8月17日
许可协议