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帮助我们从容器中获取,可以使代码更优雅。
转载请注明出处:https://www.huangchaoyu.com/2021/06/28/spring非单例模式/