目录
1 Bean 的作用域
1.1 singleton:单例模式
1.2 prototype:原型模式
1.3 Bean 的其他作用域
2 Spring 生命周期(执行流程)
2.1 启动容器
2.2 读取配置文件完成 Bean 初始化(实例化)
2.3 将 Bean 对象放到容器中
2.4 注入 Bean 属性(给当前类的属性DI,进行赋值)
3 Bean 生命周期
指定程序中某个变量的使用范围就叫做作用域。而 Bean 的作用域指的是 Bean 在 Spring 整个框架的行为模式。比如单例模式,就意味着 Bean 在整个 Spring 中只有一份,为全局共享的,如果有人修改这个值,那么另一个人拿到的,就是被修改过后的值。
该作用域下的 Bean 在 IoC 容器中只存在一个实例,所以获取 Bean 或者注入 Bean(通过 @Autowired 注入)都是同一个对象
package com.java.demo.Model;
public class User {
private String name;
private int Id;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", Id=" + Id +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return Id;
}
public void setId(int id) {
Id = id;
}
}
package com.java.demo.Model;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* 公共类
*/
@Component
public class Users {
/*
* 公共对象 -> 默认单例模式
*/
@Bean("user")
public User getUser(){
User user = new User();
user.setName("唐三藏");
user.setId(11);
return user;
}
}
package com.java.demo.Controller;
import com.java.demo.Model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@Autowired
private User user;
public void doMethod(){
User user1 = user;
System.out.println("UserController 修改之前 :User -> " + user);
user1.setName("如来佛祖");
System.out.println("UserController 修改之后 :User -> " + user);
}
}
package com.java.demo.Controller;
import com.java.demo.Model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController2 {
@Autowired
private User user;
public void doMethod(){
System.out.println("UserController2 :User -> " + user);
}
}
package com.java.demo;
import com.java.demo.Controller.UserController;
import com.java.demo.Controller.UserController2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 启动类
*/
public class App {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean("userController", UserController.class);
userController.doMethod();
UserController2 userController2 = context.getBean("userController2", UserController2.class);
userController2.doMethod();
}
}
输出:
UserController 修改之前 :User -> User{name='唐三藏', Id=11}
UserController 修改之后 :User -> User{name='如来佛祖', Id=11}
UserController2 :User -> User{name='如来佛祖', Id=11}
可以发现,单例模式中,user的姓名被修改了。
在该作用域下,每次 Bean 请求都会创建新的实例,因此获取 Bean 以及注入 Bean 都是新的对象实例。
可以使用 @Scope 标签来设置作用域。@Scope 既可以修饰方法也可以修饰类,有以下两种写法:
1. 直接设置:@Scope("prototype")
2. 枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
package com.java.demo.Model;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* 公共类
*/
@Component
public class Users {
/*
* 公共对象 -> 默认单例模式
*/
@Bean("user")
//@Scope("prototype") // 原型模式/多例模式
// 亦可写成:
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public User getUser(){
User user = new User();
user.setName("唐三藏");
user.setId(11);
return user;
}
}
输出:
UserController 修改之前 :User -> User{name='唐三藏', Id=11}
UserController 修改之后 :User -> User{name='如来佛祖', Id=11}
UserController2 :User -> User{name='唐三藏', Id=11}
只适用于 Spring MVC 项目(Spring Web):
request:请求作用域。每次 http 请求都会创建新的 Bean 实例。一次 http 请求和响应共享 Bean
session:会话作用域。一个 Http 会话共享一个 Bean。
application:应用作用域。表示的是一个 Context 容器共享一个作用域。
只适用于 websocket :
websocket 作用域
这里只会扫描包路径上的类并且使用 Spring 的注解才可以被放到容器中。
扫描 com.java.demo 包下的 Spring 注解,像 @Controller、@Service、@Component、@Repository
如果 Bean 对象需要使用其他 Bean 对象作为属性,可以使用注解:@Autowired、@Resource
Bean 的生命周期指的是 Bean 从诞生到销毁的整个生命过程,这样的过程就叫做生命周期,可以大致分为以下 5 个部分:
1. 实例化 Bean(为 Bean 分配内存空间)
2. 设置 Bean 属性(进行依赖注入,将依赖的 Bean 赋值到当前类的属性上)
3. Bean 初始化
实现了各种 Aware 通知的⽅法,如 BeanNameAware、BeanFactoryAware、 ApplicationContextAware 的接⼝⽅法;
执⾏ BeanPostProcessor 初始化前置⽅法;
执⾏ @PostConstruct 初始化⽅法,依赖注⼊操作之后被执⾏;
执⾏⾃⼰指定的 init-method ⽅法(如果有指定的话);
执⾏ BeanPostProcessor 初始化后置⽅法。
4. 使用 Bean
5. 销毁 Bean
销毁容器的各种⽅法,如 @PreDestroy、DisposableBean 接⼝⽅法、destroy- method。
package com.java.demo;
import com.java.demo.Model.User;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class BeanLifeComponent implements BeanNameAware {
@Autowired
private User user;
@Override
public void setBeanName(String s) {
System.out.println("执行了 BeanNameAware -> " + s);
}
@PostConstruct
public void doPostConstruct(){
System.out.println("执行了 @PostConstruct");
System.out.println(user.toString());
}
public void myInit(){
System.out.println("执行了 myInit");
}
@PreDestroy
public void doPreDestroy(){
System.out.println("执行了 @PreDestroy");
}
public void sayHi(){
System.out.println("使用了 Bean");
}
}
package com.java.demo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanLifeTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
BeanLifeComponent component =
context.getBean("myBean", BeanLifeComponent.class);
component.sayHi();
context.close();
}
}
输出:
执行了 BeanNameAware -> myBean
执行了 @PostConstruct
User{name='唐三藏', Id=11}
执行了 myInit
使用了 Bean
执行了 @PreDestroy