Springboot的@Scope注解
@Scope注解的作⽤详解
参考:
定义:
@Scope注解是springIoc容器中的⼀个作⽤域,在 Spring IoC 容器中具有以下⼏种作⽤域:基本作⽤域singleton(单例)、
prototype(多例),Web 作⽤域(reqeust、session、globalsession),⾃定义作⽤域
singleton单例模式(默认):全局有且仅有⼀个实例
prototype原型模式:每次获取Bean的时候会有⼀个新的实例
request: request表⽰该针对每⼀次HTTP请求都会产⽣⼀个新的bean,同时该bean仅在当前HTTP request内有效
session :session作⽤域表⽰该针对每⼀次HTTP请求都会产⽣⼀个新的bean,同时该bean仅在当前HTT
P session内有效
global session : global session作⽤域类似于标准的HTTP Session作⽤域,不过它仅仅在基于portlet的web应⽤中才有意义
直接使⽤字符串容易出问题,spring有默认的参数:
ConfigurableBeanFactory.SCOPE_PROTOTYPE,即“prototype”
ConfigurableBeanFactory.SCOPE_SINGLETON,即“singleton”
WebApplicationContext.SCOPE_REQUEST,即“request”
WebApplicationContext.SCOPE_SESSION,即“session”
使⽤
直接在bean对象⽅法上增加@Scope注解就可以
/**
定义⼀个bean对象
@return
*/
@Scope //@Scope(value = “prototype”)
@Bean(value = “user0”, name = “user0”, initMethod = “initUser”, destroyMethod = “destroyUser”)
public User getUser() {
System.out.println(“创建user实例”);
return new User(“张三”, 26);
}
@Scope注解默认的singleton实例,singleton实例的意思不管你使⽤多少次在springIOC容器中只会存在⼀个实例,演⽰如下只打印了⼀次创建实例:
AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainConfig.class); User bean2 = Bean(
User.class);
System.out.println("实例1 === "+bean2);
User bean3 = Bean(User.class);
System.out.println("实例2 === "+bean3);
//运⾏结果
创建user实例
实例1 === User [userName=张三, age=26]
实例2 === User [userName=张三, age=26]
若是改为@Scope(value="prototype")
//运⾏结果
创建user实例
实例1 === User [userName=张三, age=26]
创建user实例
实例2 === User [userName=张三, age=26]
使⽤场景
⼏乎90%以上的业务使⽤singleton单实例就可以,所以spring默认的类型也是singleton,singleton虽然保证了全局是⼀个实例,对性能有所提⾼,但是如果实例中有⾮静态变量时,会导致线程安全问题,共享资源的竞争。
当设置为prototype时:每次连接请求,都会⽣成⼀个bean实例,也会导致⼀个问题,当请求数越多,性能会降低,因为创建的实例,导致GC频繁,gc时长增加
多例
直接在controller层设置多例
在controller类上设置多例,正常
单例调⽤多例
在controller是默认的单例,service层是多例的时候,多例失效
虽然Service是多例的,但是Controller是单例的。如果给⼀个组件加上@Scope("prototype")注解,每次请求它的实例,spring的确会给返回⼀个新的。问题是这个多例对象Service是被单例对象Controller依赖的。⽽单例服务Controller初始化的时候,多例对象Service就已经注⼊了;当你去使⽤Controller的时候,Service也不会被再次创建了(注⼊时创建,⽽注⼊只有⼀次)。
⽅法1: 不使⽤@Autowired ,每次调⽤多例的时候,直接调⽤bean
⽅法2:spring的解决⽅法:设置proxyMode,每次请求的时候实例化
@Scope注解添加了⼀个proxyMode的属性,有两个值ScopedProxyMode.INTERFACES和ScopedProxyMode.TARGET_CLASS,前⼀个表⽰表⽰Service是⼀个接⼝,后⼀个表⽰Service是⼀个类。
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
案例
创建bean
@Bean
//@Scope标明模式,默认单例模式. prototype多例模式
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS) public User hbaseConnection() {
User user = new User((int) (Math.random() * 100));
System.out.println(“调⽤了hbaseConnection,User ” + Id());
return user;
}
controller引⼊并调⽤
@RestController
@RequestMapping("/demo1")
public class DemoController {
@Autowired
private User hbaseConnection;
@RequestMapping("/test")
public void test(){
System.out.println(“test:user ”+Id());
System.out.println(“test:user:id2:”+Id());
}
}
调⽤接⼝,结果为
调⽤了hbaseConnection,User 7
spring ioc注解test:user 7
调⽤了hbaseConnection,User 2
test:user:id2:2
每调⽤⼀次注⼊的对象,就会重新创建⼀个
转载于:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论