转眼之间一年过去了.发现自己好久没有写博客了.今天突发奇想想写点东西就写点简单的东西吧.接下来的一段时间,有空的话会经常写博客
工作中经常用使用spring,之间也对spring 进行过研究发现过段时间之后就忘记了.写个博客作为手记.
今天我们写一个简单的入门了解 @scope的功能
创建一个maven项目
public class Person {
private String name;
private int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
配置类
@Configuration
public class MainConfig {
@Scope
@Bean
public Person person(){
System.out.println("获取person");
return new Person("xiaodao",18);
}
}
@scope的源码
Specifies the name of the scope to use for the annotated component/bean.
* <p>Defaults to an empty string ({@code ""}) which implies
* {@link ConfigurableBeanFactory#SCOPE_SINGLETON SCOPE_SINGLETON}.
* @since 4.2
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
* @see #value
他有四种情况 分别是 singleton prototype request sesession后俩中情况基本不使用
大家都知道在springIOC容器中获取到bean是单例的.但是我们在有些情况下需要获取多实例,需要在bean 上添加作用域 @scope(“prototype”)
这样就是多实例的.
那在spring内部他是怎么运转的呢?
其实它默认在单例的情况下,Ioc容器启动时就会调用方法创建对象放到IOC容器中 以后每次获取直接到容器拿
单实例情况下
@Test
public void testIOC() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
// Object person = applicationContext.getBean("person");
// Object person1 = applicationContext.getBean("person");
// System.out.println(person.equals(person1));
}
输出:
获取person
这个时候我们并未调用 applicationContext.getBean(“person”) 他
多实例情况下
@Configuration
public class MainConfig {
@Scope("prototype")
@Bean
public Person person(){
System.out.println("获取person");
return new Person("xiaodao",18);
}
}
调用第一次
@Test
public void testIOC() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
// Object person = applicationContext.getBean("person");
// Object person1 = applicationContext.getBean("person");
// System.out.println(person.equals(person1));
}
容器启动没有输出获取person对象
调用第二次
@Test
public void testIOC() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
Object person = applicationContext.getBean("person");
Object person1 = applicationContext.getBean("person");
System.out.println(person.equals(person1));
}
控制台输出
获取person
获取person
false
我们发现他启动的时候IOC容器并没有创建这个对象而是每调用一次创建一次.
到了这里大家都很明白了吧
那这样下来项目中所以单实例的bean在IOC容器的启动的时候都加载,那有没有办法让这个Bean在调用的时候在加载呢?
答案是有的.这个时候我们的另一个注解@lazy就启到作用了.
@Configuration
public class MainConfig {
@Lazy
@Bean
public Person person(){
System.out.println("获取person");
return new Person("xiaodao",18);
}
}
这个时候容器再启动的时候就不会创建 person这个对象了.在调用的时候才会创建并且以后再去用这个对象时,不会再创建
@Test
public void testIOC() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("ioc 容器实例化...");
Object person = applicationContext.getBean("person");/**/
Object person1 = applicationContext.getBean("person");/**/
System.out.println(person==person1);
}
ioc 容器实例化...
获取person
true
1.先容器实例化并未加载person对象
2.第二次调用的时候创建
3.第三次调用的时候直接拿的IOC容器中的对象
4.是同一对象