文章目录
Bean的作用域
在IOC中可以通过 @Controller,@Service,@Repository,@Component,@Configuration,@Bean 来声明Bean对象,通过 ApplicationContext 或者 BeanFactory 来获取对象;或通过 @Autowired , Setter 方法或者构造方法等来为应用程序注入所依赖的Bean对象。
对于下面的代码,两个Bean对象输出的结果一致
java
@SpringBootTest
class DemoApplicationTests {
@Autowired
private ApplicationContext applicationContext; //Spring 容器
@Test
void contextLoads() {
Dog dog1 = applicationContext.getBean(Dog.class);
dog1.setName("狗狗1");
System.out.println(dog1);//狗狗1
System.out.println(dog1.getName());//com.example.demo.scope.Dog@2b10ace9
Dog dog2 = applicationContext.getBean(Dog.class);
System.out.println(dog2);//狗狗1
System.out.println(dog2.getName());//com.example.demo.scope.Dog@2b10ace9
}
}
在Spring中支持以下几种种作用域,后4种在Spring MVC环境才生效:
- singleton:单例作用域,每个Spring IoC容器内同名称的bean只有一个实例(单例)(默认)
- prototype:原型作用域(多例作用域),每次使用该bean时会创建新的实例(非单例)
- request:请求作用域,每个HTTP请求生命周期内,创建新的实例(web环境中,了解)
- session:会话作用域,每个HTTP Session生命周期内,创建新的实例(web环境中,了解)
- Application:全局作用域,每个ServletContext生命周期内,创建新的实例(web环境中,了解)
- websocket:HTTP WebSocket 作用域(了解)
java
@Component
public class DogBeanConfig {
@Bean
public Dog dog() {
Dog dog = new Dog();
dog.setName("旺旺");
return dog;
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public Dog singleDog() {
Dog dog = new Dog();
return dog;
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Dog prototypeDog() {
Dog dog = new Dog();
return dog;
}
@Bean
@RequestScope
public Dog requestDog() {
Dog dog = new Dog();
return dog;
}
@Bean
@SessionScope
public Dog sessionDog() {
Dog dog = new Dog();
return dog;
}
@Bean
@ApplicationScope
public Dog applicationDog() {
Dog dog = new Dog();
return dog;
}
}
java
@RestController
public class DogController {
@Autowired
private Dog singleDog;
@Autowired
private Dog prototypeDog;
@Autowired
private Dog requestDog;
@Autowired
private Dog sessionDog;
@Autowired
private Dog applicationDog;
@Autowired
private ApplicationContext applicationContext;
@RequestMapping("/single")
public String single() {
Dog contextDog = (Dog)applicationContext.getBean("singleDog");
return "dog:"+singleDog.toString()+",contextDog:"+contextDog;
}
@RequestMapping("/prototype")
public String prototype() {
Dog contextDog = (Dog)applicationContext.getBean("prototypeDog");
return "dog:"+prototypeDog.toString()+",contextDog:"+contextDog;
}
@RequestMapping("/request")
public String request() {
Dog contextDog = (Dog)applicationContext.getBean("requestDog");
return "dog:"+requestDog.toString()+",contextDog:"+contextDog.toString();
}
@RequestMapping("/session")
public String session() {
Dog contextDog = (Dog)applicationContext.getBean("sessionDog");
return "dog:"+sessionDog.toString()+",contextDog:"+contextDog.toString();
}
@RequestMapping("/application")
public String application() {
Dog contextDog = (Dog)applicationContext.getBean("applicationDog");
return "dog:"+applicationDog.toString()+",contextDog:"+contextDog.toString();
}
}
- 单例作用域:多个请求中拿到同一个对象(全部相同)
- 多例作用域:每次拿到的都不是一个对象(每次的Dog地址都不同)
- 请求作用域:在同一个请求中是一个对象,不同的请求中是另一组不同的对象(同一个URL访问中的适用applicationContext和@Autowired获取的Dog一样,另一个请求中是另一对一样的)
- 会话作用域:在同一个会话中是同一个对象,不同的会话中(同一个浏览器中的两个Dog一样,不同浏览器中不一样的一对)
- Application作用域:整个Web容器内全部相同
singleton 和 Application的区别
Application scope就是对于整个web容器来说,Bean的作⽤域是ServletContext级别的。这个和singleton有点类似,区别在于: Application scope是ServletContext的单例,singleton是⼀个ApplicationContext的单例。 在⼀个web容器中ApplicationContext可以有多个。
Bean的生命周期
Bean 的生命周期分为以下5个部分:
- 实例化(为Bean分配内存空间)
- 属性赋值(Bean注入和装配,比如 @AutoWired)
- 初始化
- 执行各种通知,如 BeanNameAware,BeanFactoryAware,ApplicationContextAware 的接口方法。
- 执行初始化方法,包括:xml定义 init-method,使用注解的方式 @PostConstruct,执行初始化后置方法(BeanPostProcessor)
- 使用Bean
- 销毁Bean
- 销毁容器的各种方法,如 @PreDestroy,DisposableBean 接口方法,destroy-method。
java
@Component
public class BeanLifeComponent {
public BeanLifeComponent() {
System.out.println("执行构造函数....");
}
@Autowired
public void setDog(Dog dog){
System.out.println("执行setter方法....");
}
@PostConstruct
public void init() {
System.out.println("执行init方法....");
}
public void use(){
System.out.println("执行use方法....");
}
@PreDestroy
public void destroy(){
System.out.println("执行destroy方法....");
}
}
java
@SpringBootTest
class SpringPrincipleApplicationTests {
@Autowired
private BeanLifeComponent beanLifeComponent;
@Test
void contextLoads() {
beanLifeComponent.use();
}
}
