1、bean的作用域
1、新建一個maven工程,添加如下依賴
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency>
2,新建一個實體Person類
package com.yefengyu.annotation.bean; public class Person { private String name; private Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
3、新建一個配置類
package com.yefengyu.annotation.config; import com.yefengyu.annotation.bean.Person; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MainConfig { @Bean public Person person() { return new Person("張三", 20); } }
4、測試
public static void main(String[] args) { ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class); Person person1 = (Person)ctx.getBean("person"); Person person2 = (Person)ctx.getBean("person"); System.out.println(person1 == person2); //true }
上面結果看出從容器多次獲取一個bean,其實都是同一個對象,這是由於bean的作用域是 單實例 造成的。
prototype:多實例的:ioc容器啟動並不會去調用方法創建對象放在容器中。每次獲取的時候才會調用方法創建對象;
singleton:單實例的(默認值):ioc容器啟動會調用方法創建對象放到ioc容器中。以后每次獲取就是直接從容器中拿,
request:同一次請求創建一個實例
session:同一個session創建一個實例
此外我們可以修改配置類,增加打印,方便觀察:
@Configuration public class MainConfig { @Bean public Person person() { System.out.println("創建Person對象"); return new Person("張三", 20); } }
我們再次運行上面的測試代碼發現 創建Person對象 這句只打印了一次。
5、使用方式:Scope注解
@Configuration public class MainConfig { @Bean @Scope("prototype") public Person person() { System.out.println("創建Person對象"); return new Person("張三", 20); } }
注意:Scope注解是對bean的作用域進行修飾,可以修改bean的作用域,可以和@Bean注解與@Component系列注解一起使用。
我們再次運行上面的測試代碼發現 創建Person對象 這句打印了兩次。並且兩個對象不相同,使用 == 比較返回 false.
Scope中的值可以使用上面的字符串,例如prototype,也可以使用
- ConfigurableBeanFactory.SCOPE_PROTOTYPE
- ConfigurableBeanFactory.SCOPE_SINGLETON
- WebApplicationContext.SCOPE_REQUEST
- WebApplicationContext.SCOPE_SESSION
2、懶加載
專門針對單實類,也叫延遲加載。
@Configuration public class MainConfig { @Bean public Person person() { System.out.println("創建Person對象"); return new Person("張三", 20); } }
單實例bean:默認在容器啟動的時候創建對象;
AnnotationConfigApplicationContext ctx =new AnnotationConfigApplicationContext(MainConf.class);
下面這段測試代碼並沒有使用到 person ,但是通過打印我們可以看出已經加載了Person對象。
public static void main(String[] args) { ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class); String[] names = ctx.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } }
創建Person對象
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
現在我們加上一個注解@Lazy
@Configuration public class MainConfig { @Bean @Lazy public Person person() { System.out.println("創建Person對象"); return new Person("張三", 20); } }
此時再次測試,得出的結果如下
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
說明在延遲加載的情況下,如果沒有使用到bean,那么就不會在容器真正創建一個對象(沒有打印 :創建Person對象 ),現在我們在測試代碼加上對 person對象的獲取。
public static void main(String[] args) { ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class); String[] names = ctx.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } Person person= (Person)ctx.getBean("person"); }
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person 創建Person對象
懶加載歸納:容器啟動不創建對象。第一次使用(獲取)Bean時創建對象,並初始化