深入探究Spring底层核心原理
作者:胡尚 发布时间:2023-03-05 08:32:16
Spring底层核心原理
下面这几行代码是一个Spring的入门代码,第一行是通过java配置类 注解的方式创建一个Spring容器,第二行是通过XML配置文件的方式创建一个Spring容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
userService.test();
最后两行代码就是从Spring容器中拿一个Bean对象并执行方法。那么Spring是如何创建一个Bean对象的嘞?
Bean的生命周期
推断构造方法,并执行得到普通对象
依赖注入
aware回调
初始化前
执行BeanPostProcessor
接口中的postProcessBeforeInitialization()
方法
初始化
执行有@PostConstruct
注解的方法执行
InitializingBean
接口中的afterPropertiesSet()
方法
执行XML配置文件中init-method
属性指定的方法
初始化后
执行BeanPostProcessor
接口中的postProcessAfterInitialization()
方法
普通对象/代理对象 存入容器中
使用
销毁
执行DisposableBean
接口的destroy()
方法
有@PreDestroy
注解的方法
XML 配置文件中destroy-method
属性指定的方法
推断构造方法
如果没有写构造方法,那么Spring会执行默认空参的构造方法
如果显示写了一个构造方法,那么Spring就会使用这个构造方法,构造方法中如果有参数那么会进行依赖注入
如果显示写了多个构造方法并有空参的构造方法时,会执行空参的构造方法
如果显示写了多个构造方法没有空参的构造方法时,运行时会报错。解决方法是在要执行的构造方法上加@Autowired
注解
AOP原理
cjlib和jdk两种 * 的实现都是有一个target属性来存储普通对象,代理对象中重写要执行的方法,首先执行增强逻辑,然后通过target属性去执行目标方法。伪代码如下:
public class UserServiceProxy extends UserService{
private UserService target;
public void test(){
// TODO 增强业务
target.test();
// TODO 增强业务
}
}
那么如何判断一个Bean是否需要进行AOP创建一个普通对象嘞?
遍历所有有
@Aspect
注解的切面Bean遍历所有的方法
判断方法上的切点表达式是否和当前正在创建的Bean匹配
如果匹配则把这个切面中增强方法存入一个Map缓存中
真正要执行代理对象的方法时会从缓存中取出相应的增强逻辑来执行,再去执行目标方法。
Spring事务
Spring中如果要使用事务需要配置一个JdbcTemplate和一个事务管理器,它们俩都需要配置DataSource。
@ComponentScan("com.hs")
@Configuration
public class AppConfig {
@Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource());
return transactionManager;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/hs?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
}
Spring事务大致执行流程如下:
判断要执行的方法上是否存在
@Transcational
注解如果存在则通过事务管理器创建一个connection连接对象
autoCommit设置为false
去执行目标方法target.method()
如果出现了异常则回滚rollback(),没有异常则提交commit()
如果上面的配置类中不加@Configuration
注解,那么Spring的事务会失效。原因如下:
JdbcTemplate和事务管理器都需要DataSource,都会调用dataSource()
获取。如果不加@Configuration
注解,那么他们俩获取的DataSource就不是同一个。
代理对象中操作的是事务管理器的连接对象,而业务方法却是使用的JdbcTemplate,所以就导致了Spring事务失效。
而如果加上了@Configuration
注解,在调用dataSource()
时会先去Spring容器中找DataSource,如果没找到才回去调用方法创建一个。
来源:https://blog.csdn.net/qq_44027353/article/details/130223776


猜你喜欢
- 1. 程序计数器(线程私有)程序计数器是一块比较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器(切换线程后,能恢复到正确的执行位
- 一、线程组 /** * A thread group represents a set of threads. In addition,
- 你是否受够了每次修改静态文件都要重启服务器?有时候在一些公司前后端的职责没有那么的明确,往往后台人员也要去写一些页面,像jsp页面,或者其他
- 本次就是记录一下我的开发过程,不是教程,纯属自己做个笔记。现在项目有个需求,需要用户在公众号发送图片消息的时候,我后台程序能接收到这个图片,
- Room在SQLite基础上做了ORM封装,使用起来类似JPA,不需要写太多的sql。导入依赖//roomdef room_version=
- 一、什么是重量级锁当有大量的线程都在竞争同一把锁的时候,这个时候加的锁,就是重量级锁。这个重量级锁其实指的就是JVM内部的ObjectMon
- git仓库直达List<String> strings = Lists.newArrayList("name=kk&q
- Unity2018已经把打包过程简化很多了我们只需要关心两个API:1.BuildPipline.BuildAssetBundles() 打
- 一、java内存区域Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和
- springboot上传文件大小的配置我这里记录两种,一种是设置在配置文件里只有两行代码,一种是加个Bean首先第一种:applicatio
- 前言数字时间戳技术是数字签名技术一种变种的应用。是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08
- list stream: reduce的使用stream 中的 reduce 的主要作用就是stream中元素进行组合,组合的方式可以是加减
- 一个真实的故事大学的时候就开过一门课程,讲设计模式,可是大学生没什么编程实践经验,在大学里面听设计模式的感觉,就像听天书。听着都有道理,可是
- 上一篇我们学习了自定义ViewGroup的基本步骤,并做了一个CustomGridLayout的实例,这篇我们继续来说说自定义ViewGro
- 本文实例讲述了C#操作session的类。分享给大家供大家参考。具体分析如下:这个C#类对session操作进行了再次封装,可以大大简化se
- 正常状态是UP,跳闸是⼀种状态CIRCUIT_OPEN,可以通过/health查看,前提是工程中需要引入SpringBoot的actuato
- 一、什么是网关限流:在微服务架构中,网关层可以屏蔽外部服务直接对内部服务进行调用,对内部服务起到隔离保护的作用,网关限流,顾名思义,就是通过
- 本文实例为大家分享了Android自定义圆环倒计时控件的具体代码,供大家参考,具体内容如下先来一张最终效果图:主要思路: 在画渐变
- java获取文件的inode标识符,如果文件被删除或者重命名,inode的值会发生变更,因此可以在第一次加载File之后记录inode,后续
- 目录1、在运行时,由java解释器自动引入,而不用import语句引入的包是()。2、以下关于集合类ArrayList、LinkedList