目录Spring原理Bean的作用域验证是单例的多例的作用域request的作用域session的作用域application的作用域Bean的生命周期代码的使用源码阅读SpringBoot自动配置总结Spring原理Bean的作用域概念:从Context中获取对象,得到的都是同一个,这种行为模式,就称为bean的作用域
多次获取,拿到的Bean的对象都是同一个
在Spring中支持6种作用域,后4种在Spring MVC环境才生效
(1) singleton:单例作用域
每个Spring IoC容器内同名称的bean只有一个实例(单例)(默认)
(2) prototype:原型作用域(多例作用域)
每次使用该bean时会创建新的实例(非单例)
(3) request:请求作用域
每个HTTP 请求生命周期内, 创建新的实例(web环境中, 了解)
(4) session:会话作用域
每个HTTP Session生命周期内, 创建新的实例(web环境中, 了解)
(5) Application: 全局作用域
每个ServletContext生命周期内, 创建新的实例(web环境中, 了解)
(6) websocket:HTTP WebSocket 作用域
每个WebSocket生命周期内, 创建新的实例(web环境中,了解)验证是单例的从context中获取对象属性注入获取对象@Configuration public class BeanConfig {@Bean public User user1(){return new User(1,"zhangsan");}
// 声明作用的范围(声明了一个单例的作用域)// 声明了一个单例的对象@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)// @Scope("singleton")@Bean public User singleUser(){return new User();}}
// 有多个@Autowired的时候,指定名称使用哪个@Resource(name = "singleUser") private User singleUser;
@RequestMapping("scope")@RestController public class BeanScopeController {@Autowired private ConfigurableApplicationContext context;
// 有多个@Autowired的时候,指定名称使用哪个@Resource(name = "singleUser") private User singleUser;
@RequestMapping("/single") public String single(){// 1. 从context中获取对象String user = (String) context.getBean("singleUser");// 2. 属性注入获取对象
return "从context中获取的对象 " + System.identityHashCode(user)+ "属性注入获取的对象" + System.identityHashCode(singleUser);}}结果展示:可以看出他们获取的是同一个对象
多例的作用域多例模式(原型模式)
属性注入在程序启动的时候会创建一个对象,之后再重新启动,才会改变context获取的对象,每次重新启动都会重新获取对象,因此每次对象都会发生变化
//对象@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)@Bean public User prototypeUser(){return new User();}
// 注解@Resource(name = "prototypeUser") private User prototypeUser;
@RequestMapping("/phototype") public String phototype(){// 1. 从context中获取对象User user = (User) context.getBean("prototypeUser");// 2. 属性注入获取对象
return "从context中获取的对象 " + System.identityHashCode(user)+ "属性注入获取的对象" + System.identityHashCode(prototypeUser);}展示效果:每次刷新,拿到的不是同一个对象,每次请求都会生成一个新的对象
出现的问题:没有验证成功的原因是我们写的是同一个User对象,@Data中的hashcode()会根据id判断他们是否是同一个对象,**这里的new User()都是同一个对象,那么这里就判断了他们是同一个对象,Spring进行了优化,**因此每次request刷新都不变,理论上每次刷新,都会创建一个新的对象,每次都会变化
这里就要使用jdk,自带的toString()方法,jdk有hashcode()方法,用自带的toString()方法,它每次new都会生成不同的对象,因此可以看出request,每次都是变化的了
所以这里不同@Data,而用@Getter和@Setter
对上面问题的再一次解释:
Spring使用了代理模式,所以代理的User,每次都是同一个
Spring中才有代理模式:
request的作用域@RequestScope等同于@Scope,这两者含义是一样的
虽然是同一个对象,但是每次请求都会重新创建对象
// request的作用域@RequestScope@Bean public User requestUser(){return new User();}
// 注解的方式@Resource(name = "requestUser") private User requestUser;
@RequestMapping("/request") public String request(){// 1. 从context中获取对象User user = (User) context.getBean("requestUser");// 2. 属性注入获取对象
return "从context中获取的对象 " + System.identityHashCode(user)+ "属性注入获取的对象" + System.identityHashCode(requestUser);}session的作用域在不同的浏览器下,是不同的会话,自然会出现不同的地址@SessionScope@Bean public User sessionUser(){return new User();}@Resource(name = "sessionUser") private User sessionUser;
@RequestMapping("/session") public String session(){// 1. 从context中获取对象User user = (User) context.getBean("sessionUser");// 2. 属性注入获取对象
return "从context中获取的对象 " + System.identityHashCode(user)+ "属性注入获取的对象" + System.identityHashCode(sessionUser);}
效果展示:
如果是同一个浏览器,并且没有清除cookie,那么session不会发生变化
如果是不同的浏览器,就是不同的cookie,session自然会发生变化
application的作用域application的作用域:在整个应用中都是同一个的,和我们的单例一样,在同一个应用中都是同一个两者的区别:一个web容器中(一个tomcat中),可以部署多个服务(多个ApplicationContext),而一个Web容器中有多个ServletContext - 每个Web应用都有自己独立的ServletContext实例一个tomcat可以启动多个web服务
@ApplicationScope@Bean("applicationUser")// 指定名字public User applicationUser(){return new User();}
// 注解注入@Resource(name = "applicationUser") private User applicationUser;
@RequestMapping("/application") public String application(){// 1. 从context中获取对象User user = (User) context.getBean("applicationUser");// 2. 属性注入获取对象
return "从context中获取的对象 " + user+ "属性注入获取的对象" + applicationUser;}在不同的浏览器中,进行展示,都是同一个
Bean的生命周期代码的使用对象的生命周期:生命周期指的是一个对象从诞生到销毁的整个生命过程, 我们把这个过程就叫做一个对象的生命周期。
Bean 的生命周期分为以下5个部分:
2. 实例化(为Bean分配内存空间)
3. 属性赋值(Bean注入和装配, 比如 @AutoWired )
4. 初始化
a. 执行各种通知, 如 BeanNameAware , BeanFactoryAware ,
ApplicationContextAware 的接口方法.
b. 执行初始化方法
▪ xml定义 init-method
▪ 使用注解的方式 @PostConstruct
▪ 执行初始化后置方法( BeanPostProcessor )
5. 使用Bean
6. 销毁Bean
a. 销毁容器的各种方法, 如 @PreDestroy , DisposableBean 接口方法, destroy-
method
举个例子:
2. 写一个案例,来验证Bean的生命周期
// BeanLifeComponent@Component public class BeanLifeComponent {private User user;// 构造public BeanLifeComponent() {System.out.println("执行构造方法~");}
// 属性注入// 指定注入的对象// 表示注入的user1对象@Qualifier("user1")@Autowired public void setUser1(User user) {this.user = user;System.out.println("属性注入~");}
// 初始化// 使用@PostConstruct实现初始化@PostConstruct // 这个用的比较多public void init(){System.out.println("执行初始化方法~");}
// 使用public void use(){System.out.println("执行use方法~");}
// 销毁// 基本上不会用@PreDestroy // pre表示 bean 销毁前执行,销毁的时候就直接清理对象了public void destroy(){System.out.println("执行destroy销毁方法~");}}
// 测试方法public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(SpringConfigApplication.class, args);BeanLifeComponent lifeComponent = context.getBean(BeanLifeComponent.class);lifeComponent.use();// 有不手动点击结束进程的方式来执行destroy方法// ((AbstractApplicationContext)context).destroy();}
展示效果:
手动关闭进程:
源码阅读了解生命周期的分类bean的实例化,属性注入,bean的初始化
2. 执行各种通知,这些通知都是在初始化方法之前执行,属性注入之后执行的
SpringBoot自动配置这些注解的底层就是Spring自动配置的元注解:是注解其他注解的注解
有选择地导入配置类
总结到此这篇关于Java Spring原理之Bean的作用域、Bean的生命周期及Spring自动配置的文章就介绍到这了,更多相关Java Spring原理详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:详解Spring中Bean的生命周期和作用域及实现方式浅谈Spring中Bean的作用域、生命周期Spring Bean中的六种作用域你了解吗深入了解Spring中Bean的作用域和生命周期浅谈Spring Bean的作用域之间有什么区别Spring 框架中的 Bean 作用域(Scope)使用详解Spring中Bean的作用域与生命周期详解详解Spring中Bean的作用域与生命周期
