【Spring系列】- Bean生命周期底层原理
Bean生命周期底层原理
生命不息,写作不止
继续踏上学习之路,学之分享笔记
总有一天我也能像各位大佬一样
一个有梦有戏的人 @怒放吧德德
分享学习心得,欢迎指正,大家一起学习成长!
前言
上次学到动手模拟Spring底层实现,简单学习了一下Spring,对spring有所了解,接着就来分析spring中bean的生命周期的步步流程。
流程
接下来会根据Bean生命周期一步一步去学习,spring在创建bean对象的过程中,还是做了许多的操作,从依赖注入,通过初始化以及前后操作,最后创建了bean对象放入Map单例池,对于多例是不放进去的。
本次实验使用的pom依赖坐标如下
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.15</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.15</version>
</dependency>
依赖注入
首先是根据无参构造方法去获取对象,通过这个类获取所有字段,在来判断是否有Autowired注解,在给这个属性去赋值。
UserService userService1 = new UserService();
for (Field field : userService1.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
field.set(userService1, ???);
}
}
初始化前执行方法
通过对象获取所有方法,我们在需要执行的方法上使用PostConstruct注解,然后就只需要遍历这些方法,去判断是否含有这个注解,在使用invoke去执行方法。
for (Method method : userService1.getClass().getMethods()) {
if (method.isAnnotationPresent(PostConstruct.class)) {
method.invoke(userService1, null);
}
}
初始化
除了使用PostConstruct注解去执行方法,还有一种方法是通过去实现InitializingBean接口,并且需要实现其未实现的方法afterPropertiesSet。
那么对象是如何知道在spring中会有afterPropertiesSet这个方法呢?可以通过反射判断是否有这个方法,有的话就直接执行。在spring中,他是采用去判断对象是否有实现InitializingBean这个类,有的话会强转成这个类,再去执行这个类的方法
推断构造方法底层原理
如果有多个构造方法,回去寻找是否有无参的,找到了,就直接使用,没找到就会报错。如果是使用了多个构造方法,可以使用Autowired去告诉spring需要使用那个构造方法。如果在构造方法里需要一个bean对象,那么spring会去map单例池中去查找相应的bean对象,如果没找到,就会去创建bean对象,但如果是多例bean的话,就不需要查找,直接创建一个对象。
当我们使用构造方法获取bean对象时,一般是通过类上使用Component注解去定义一个首位字母小写的bean对象,也可以是通过Bean注解,去创建不同bean名的相同类型的bean对象。
如下代码,在配置中添加两个bean对象,包括类上自己生成的一共三个bean对象。分别为{roleService、roleService1、roleService2}。这三个的类型一样,但是对象是不同的,名字不同,bean对象就不同。
@ComponentScan("com.lyd")
public class ApplicationConfig {
@Bean
public RoleService roleService1() {
return new RoleService();
}
@Bean
public RoleService roleService2() {
return new RoleService();
}
}
当使用其中一个beanName都是可以的
@Component
public class UserService {
private RoleService roleService;
public UserService(RoleService roleService1) {
this.roleService = roleService1;
}
public void test(){
System.out.println(roleService);
}
}
但是如果使用的不是上面三个其中之一,就会报错。但是能看到他找到了三个。
AOP - 动态代理
使用AOP就是需要使用代理对象,然而代理对象与第一次的对象是不一样的。
首先定义一个aop切面
@Aspect
@Component
public class AopAspect {
@Before("execution(public void com.lyd.service.UserService.test())")
public void beanBefore(JoinPoint joinPoint) {
System.out.println("before");
}
}
在配置类中标上注解 @EnableAspectJAutoProxy 开启切面,这样切面就会实现了。再来debug调用userService的test方法,可以观察到,获得的对象是CGLIB代理的对象
并且能看到里面的roleService是没有值的。但是从运行结果来看,先走了切面,最后的roleService是有值的。
然而这都是因为代理类是父子级关系来实现的。接下来一步一步分析。
spring通过代理对象,就是为了能够先执行切面方法,在来执行原本对象的方法。首先,spring会生成一个对象:UserServiceProxy,这个就是UserService对象的代理对象。我们用java面向对象思想来思考,代理对象会继承UserService类,他内部重写了父类的test方法,在里面去执行切面的逻辑,接着通过super.test调用父类方法。这个方法虽然是可以实现,但是在spring中却不是这样的。
在Spring中,代理对象里面还会定义一个父类对象UserService target,这个对象最终会赋值这个类生成的对象,也就是bean生命周期最开始遇到的那个对象。Spring通过调用target.test()实现。说白了还是使用了最原来的那个对象去执行的方法。
创作不易,如有错误请指正,感谢观看!记得点赞哦!
【Spring系列】- Bean生命周期底层原理的更多相关文章
- Spring源码系列 — Bean生命周期
前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...
- Spring中Bean生命周期
Spring中的bean生命周期是一个重要的点,只有理解Bean的生命周期,在开发中会对你理解代码是非常有用的.对于Bean的周期,个人认为可以分为四个阶段.第一阶段:Bean的实例化,在该阶段主要是 ...
- Spring:Bean生命周期
关于Bean生命周期,我在网上找了两张图: 图1: 图2: 总结起来就是: Bean构建: Bean对象创建 > @Autowired | @Resource> @PostConstruc ...
- spring注解-bean生命周期
https://www.jianshu.com/p/70b935f2b3fe bean的生命周期 bean创建---初始化----销毁的过程 容器管理bean的生命周期 对象创建:容器启动后调用bea ...
- 2.Spring的Bean生命周期和组装方式
1.Spring IoC容器概述 Spring IoC容器: Spring容器即体现了IoC原理 Spring容器通过读取配置元数据负责对Beans实例化.配置和装配 配置元数据可以用X ...
- Spring的Bean生命周期理解
首先,在经历过很多次的面试之后,一直不能很好的叙述关于springbean的生命周期这个概念.今日对于springBean的生命周期进行一个总结. 一.springBean的生命周期: 如下图所示: ...
- Spring 的 Bean 生命周期,11 张高清流程图及代码,深度解析
在网上已经有跟多Bean的生命周期的博客,但是很多都是基于比较老的版本了,最近吧整个流程化成了一个流程图.待会儿使用流程图,说明以及代码的形式来说明整个声明周期的流程.注意因为代码比较多,这里的流程图 ...
- spring学习笔记(四)我对spring中bean生命周期的理解
我相信大部分同学对spring中bean的生命周期都不陌生,但是如果要详细的说出每一个步骤,可能能说出来的也不多,我之前也是这样,前几天调了一下spring的源码,看了一点书,突然一下明朗了,理解了s ...
- Spring配置文件-Bean生命周期配置(init-method方法,destory-method方法)
1.UserDaoImpl类 public class UserDaoImpl implements UserDao { public UserDaoImpl(){ System.out.printl ...
- [转]Spring 之 Bean 生命周期
Spring 容器中可以注册多个后处理器,只要它们同时实现 org.springframework.core.Ordered 接口. 下载文件 :内容来自 <精通Spring+4.x++企业应用 ...
随机推荐
- 表单动态增加div元素提交方法
实现的效果如下: 1 var detail_div = 1; 2 var i=0; 3 function add_div() { 4 var e = document.getElementById(& ...
- Nginx location总结
最近操作Nginx.conf 的location部分,发现了一个巨坑,在这做个记录 当我用一下配置时 location = / { root /usr/share/nginx/html; index ...
- Java---Stream入门
由于本文需要有一定的Lambda基础,所以如果不懂什么是Lambda的同学请移步:Java---Lambda 学习Stream的目的 函数式编程渐渐变成主流,而Stream是函数式编程的重点. 相对于 ...
- Jmeter中的JSON提取器用法
一.使用前提 一般来说JSON提取器只适用于响应结果中返回的是json数据 二.需求 在下一个接口调用上一个接口的数据,如:请求1返回的结果,处理以后作为请求2的参数使用. 首先需要下载JSON Ex ...
- 视频结构化 AI 推理流程
「视频结构化」是一种 AI 落地的工程化实现,目的是把 AI 模型推理流程能够一般化.它输入视频,输出结构化数据,将结果给到业务系统去形成某些行业的解决方案. 换个角度,如果你想用摄像头来实现某些智能 ...
- Nginx 动态压缩与静态压缩,显著提高前后端分离项目响应速度!
文章转载自:https://mp.weixin.qq.com/s/NuTmEUQU5L69is53bCauKA Nginx 中配置前端的 gzip 压缩,有两种思路: Nginx 动态压缩,静态文件还 ...
- 采用docker方式安装ElastAlert,图形化配置告警规则----具体内容有删改,仅供查看
1.创建几个文件夹保存ElastAlert相关配置信息,用来挂载到容器中使用 2.编写核心配置,创建 ${ELASTALERT}/config/config.yaml用来存储核心配置: 3.Elast ...
- 在 Linux 中找出 CPU 占用高的进程
列出系统中 CPU 占用高的进程列表来确定.我认为只有两种方法能实现:使用 top 命令 和 ps 命令.出于一些理由,我更倾向于用 top 命令而不是 ps 命令.但是两个工具都能达到你要的目的,所 ...
- SQLyog企业版
一.下载与安装 1.SQLyog的下载 链接:https://www.aliyundrive.com/s/11ZuFqB1z4E提取码:63fu 2.SQLyog的安装 双击下载程序,可以选择默认安装 ...
- WPF 的内部世界(Binding)
目录 一.控件与布局 二.Binding基础 前言 "一桥飞架南北, 天堑变通途" 写于1956年,1957年武汉长江大桥建成, 称之为:一桥飞架南北,大堑变通途.它形象地描述武汉 ...