@@ -4428,8 +4428,6 @@ Spring容器中的bean定义冲突问题
44284428
44294429
44304430
4431-
4432-
44334431***
44344432
44354433
@@ -7388,26 +7386,24 @@ Spirng可以通过配置的形式控制使用的代理形式,Spring会先判
73887386
73897387#### 事务介绍
73907388
7391- 事务:数据库中多个操作合并在一起形成的操作序列
7392-
7393- Spring事务一般加到业务层,对应着业务的操作,数据层有自己默认的隔离界别。Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,Spring是无法提供事务功能的,Spring只提供统一事务管理接口
7389+ 事务:数据库中多个操作合并在一起形成的操作序列,事务特征(ACID)
73947390
73957391作用:
73967392
73977393* 当数据库操作序列中个别操作失败时,提供一种方式使数据库状态恢复到正常状态(**A**),保障数据库即使在异常状态下仍能保持数据一致性(**C**)(要么操作前状态,要么操作后状态)
73987394* 当出现并发访问数据库时,在多个访问间进行相互隔离,防止并发访问操作结果互相干扰(**I**)
73997395
7400- 事务特征(ACID):
7396+ Spring事务一般加到业务层,对应着业务的操作,Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,Spring是无法提供事务功能的,Spring只提供统一事务管理接口
74017397
7402- Spring会在事务开始时 ,根据当前环境中设置的隔离级别,调整数据库隔离级别,由此保持一致。** 程序是否支持事务首先取决于数据库 ,比如使用 MySQL ,如果选择的是 innodb 引擎,那么是可以支持事务的。但是,如果MySQL使用的是 myisam 引擎的话, 那从根上就是不支持事务的**
7398+ Spring在事务开始时 ,根据当前环境中设置的隔离级别,调整数据库隔离级别,由此保持一致。程序是否支持事务首先取决于数据库 ,比如MySQL ,如果是 ** innodb 引擎**,是支持事务的;如果MySQL使用myisam引擎, 那从根上就是不支持事务的
74037399
74047400**保证原子性**:
74057401
74067402* 要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行**回滚**
7407- * 在 MySQL 中,恢复机制是通过**回滚日志(undo log)** 实现,所有事务进行的修改都会先先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,直接利用**回滚日志**中的信息将数据回滚到修改之前的样子即可
7403+ * 在 MySQL 中,恢复机制是通过**回滚日志(undo log)** 实现,所有事务进行的修改都会先先记录到这个回滚日志中,然后再执行相关的操作。如果执行过程中遇到异常的话,直接利用回滚日志中的信息将数据回滚到修改之前的样子即可
74087404* 回滚日志会先于数据持久化到磁盘上,这样保证了即使遇到数据库突然宕机等情况,当用户再次启动数据库的时候,数据库还能够通过查询回滚日志来回滚将之前未完成的事务
74097405
7410-
7406+ 事务不生效的问题:-->**Transactional注解**
74117407
74127408
74137409
@@ -8065,16 +8061,44 @@ public class TransactionManagerConfig {
80658061 noRollbackFor = {},
80668062 propagation = Propagation.REQUIRES_NEW
80678063)
8068- public interface AccountService {}
8064+ public void addAccount {}
80698065```
80708066
80718067说明:
80728068
8073- * 接口上配置总体的,方法中配置具体的
8074- * `@Transactional` 注解只有作用到 public 方法上事务才生效,不推荐在接口上使用;
8075- * 避免同一个类中调用 `@Transactional` 注解的方法,这样会导致事务失效;
8069+ * `@Transactional` 注解只有作用到 public 方法上事务才生效
8070+ * 不推荐在接口上使用`@Transactional` 注解
8071+ 原因:在接口上使用注解,只有**在使用基于接口的代理时才会生效**,因为注解是不能继承的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别
8072+ * 避免同一个类中调用 `@Transactional` 注解的方法,这样会导致事务失效
80768073* 正确的设置 `@Transactional` 的 rollbackFor 和 propagation 属性,否则事务可能会回滚失败
80778074
8075+ 面试题:**事务不生效的问题**
8076+
8077+ * 情况1:确认创建的mysql数据库表引擎是InnoDB,MyISAM不支持事务
8078+
8079+ * 情况2:注解到protected,private 方法上事务不生效,但不会报错
8080+
8081+ * 情况3:在业务层捕捉异常后未向上抛出,事务不生效
8082+
8083+ 原因:在业务层捕捉并处理了异常(try..catch)等于把异常处理掉了,Spring就不知道这里有错,也不会主动去回滚数据,推荐做法是在业务层统一抛出异常,然后在控制层统一处理
8084+
8085+ * 情况4:遇到非检测异常时,事务不开启,也无法回滚
8086+
8087+ 原因:Spring的默认的事务规则是遇到运行异常(RuntimeException)和程序错误(Error)才会回滚。想针对非检测异常进行事务回滚,可以在@Transactional 注解里使用rollbackFor 属性明确指定异常
8088+
8089+ * 情况5:Spring的事务传播策略在内部方法调用时将不起作用,事务注解加到要调用方法上
8090+
8091+ ```java
8092+ @Transactional
8093+ public int add(){
8094+ update();
8095+ }
8096+ //注解添加在update方法上无效,需要添加到add()方法上
8097+ public int update(){}
8098+ ```
8099+
8100+
8101+
80788102
80798103
80808104***
@@ -8098,8 +8122,6 @@ public interface AccountService{}
80988122* 业务层
80998123
81008124 ```java
8101- //对当前接口的所有方法添加事务
8102- @Transactional(isolation = Isolation.DEFAULT)
81038125 public interface AccountService {
81048126 //对当前方法添加事务,该配置将替换接口的配置
81058127 @Transactional(
@@ -8113,9 +8135,9 @@ public interface AccountService{}
81138135 public void transfer(String outName, String inName, Double money);
81148136 }
81158137 ```
8116-
8138+
81178139 ```java
8118- public class AccountServiceImpl implements AccountService {
8140+ public class AccountServiceImpl implements AccountService {
81198141 @Autowired
81208142 private AccountDao accountDao;
81218143 public void transfer(String outName, String inName, Double money) {
@@ -8125,7 +8147,7 @@ public interface AccountService{}
81258147 }
81268148 }
81278149 ```
8128-
8150+
81298151* 添加文件Spring.config、Mybatis.config、JDBCConfig (参考ioc_Mybatis)、TransactionManagerConfig
81308152
81318153 ```java
@@ -8375,10 +8397,7 @@ ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.
83758397
83768398 * 获取到以后进行实例化,然后直接return 循环依赖阶段有代码详解
83778399
8378- 查询成功:`getObjectForBeanInstance`从缓存中获取的是原始状态的bean,需要对bean进行实例化
8379-
8380- * 验证 bean 类型:判断是否是工厂bean,对非 FactoryBean 不做处理
8381- * 处理 FactoryBean:先对bean进行转换,再委托给getObjectFromFactoryBean()方法进行处理
8400+ 查询成功:`getObjectForBeanInstance`获取给定bean实例的对象,最后详解
83828401
83838402 依次进行:循环依赖检查、父工厂检查、标记Bean已经创建、读取XML配置文件初始化bean的属性
83848403
@@ -8387,11 +8406,16 @@ ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.
83878406 * `singletonObjects.get(beanName)`:检查是否已经被加载,单例模式复用已经创建的bean
83888407 * `beforeSingletonCreation(beanName)`:初始化前操作,校验是否 beanName 是否有别的线程在初始化,并记录beanName的初始化状态
83898408 * `singletonObject = singletonFactory.getObject()`:**实例化 bean**,第二阶段详解
8390- * `singletonObject = singletonFactory.getObject()`:创建bean
8391- * 创建完成以后,Bean已经填充好,是一个完整的可使用的Bean
8392- * `afterSingletonCreation(beanName)`:初始化后的操作,移除初始化状态
8393- * `addSingleton(beanName, singletonObject)`:添加单例池,从二级三级缓存移除
8394- * `getTypeConverter().convertIfNecessary()`:检查所需的类型是否与实际bean实例的类型匹配
8409+ * **创建完成以后,Bean已经填充好,是一个完整的可使用的Bean**
8410+ * `afterSingletonCreation(beanName)`:初始化后的操作,移除初始化状态
8411+ * `addSingleton(beanName, singletonObject)`:添加单例池,从二级三级缓存移除
8412+
8413+ **获取对象**:`getObjectForBeanInstance`获取给定bean实例的对象,从缓存中获取的bean是原始状态
8414+
8415+ * 验证 bean 类型:判断是否是工厂bean,对非 FactoryBean 不做处理
8416+ * 处理 FactoryBean:先对bean进行转换,再委托给getObjectFromFactoryBean()方法进行处理
8417+
8418+ 依赖检查:`convertIfNecessary()`检查所需的类型是否与实际bean实例的类型匹配
83958419
83968420 ```java
83978421 sharedInstance = getSingleton(beanName, () -> {
@@ -8414,7 +8438,7 @@ ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.
84148438 **开始创建**:`doCreateBean(beanName, RootBeanDefinition, Object[] args)`
84158439
84168440 * **创建实例**:`createBeanInstance(beanName, RootBeanDefinition, Object[] args)`
8417- * 优先级从高到低:工厂方法、有参构造函数 、默认构造函数
8441+ * 优先级从高到低:工厂方法、有参**构造函数** 、默认构造函数
84188442 * 将 BeanDifinition 转化成 BeanWrapper,Spring给所有创建的Bean实例包装成BeanWrapper,BeanWrapper是对反射相关API的简单封装,使得上层使用反射完成相关的业务逻辑大大简化
84198443
84208444 * 后置处理:`applyMergedBeanDefinitionPostProcessors()`
@@ -8437,9 +8461,9 @@ ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.
84378461 * `InjectionMetadata.InjectedElement.inject()`:注入数据(重写实现,注入变量或方法)
84388462 * `DefaultListableBeanFactory.resolveDependency()`:解决依赖
84398463 * `doResolveDependency().resolveCandidate()`:通过工厂获取Bean对象
8440- * `registerDependentBeans()`:将Bean注册为Autowired自动装配的Bean
8464+ * `registerDependentBeans()`:** 将Bean注册为Autowired自动装配的Bean**
84418465 * `ReflectionUtils.makeAccessible()`:修改访问权限,true代表暴力破解
8442- * `method.invoke`:利用反射为此对象赋值
8466+ * `method.invoke() `:利用反射为此对象赋值
84438467 * 填充属性:`applyPropertyValues()`,将所有解析的PropertyValues的属性填充至BeanWrapper
84448468
84458469 * **初始化**:`initializeBean(String, Object, RootBeanDefinition)`
@@ -8472,6 +8496,8 @@ ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.
84728496
84738497 * 根据不同的scope进行disposableBean的注册,在销毁对象时调用destory()
84748498
8499+ 总结:Bean的初始化过程:共仓
8500+
84758501
84768502
84778503****
@@ -8740,7 +8766,7 @@ AutowiredAnnotationBeanPostProcessor间接实现InstantiationAwareBeanPostProces
87408766
87418767* Spring容器在每个Bean实例化之后,调用AutowiredAnnotationBeanPostProcessor的`postProcessMergedBeanDefinition`方法,查找该Bean是否有@Autowired注解
87428768
8743- * Spring在每个Bean实例化时,调用 `populateBean`进行属性注入的时候,即调用`postProcessPropertyValues `方法,查找该Bean是否有 @Autowired注解
8769+ * Spring在每个Bean调用 `populateBean`进行属性注入的时候,即调用`postProcessProperties `方法,查找该Bean属性是否有 @Autowired注解
87448770
87458771
87468772
@@ -13634,6 +13660,35 @@ public @interface EnableUser {
1363413660
1363513661
1363613662
13663+ ***
13664+
13665+
13666+
13667+ ### Scheduled
13668+
13669+ @Scheduled 注解:SpringBoot提供的用于定时任务控制的注解
13670+
13671+ @EnableScheduling :启动定时任务,Scheduled配合此注解使用,在启动类上添加该注解
13672+
13673+ 作用:用于控制任务在某个指定时间执行,或者每隔一段时间执行
13674+
13675+ 注意:@Scheduled 不能修饰私有方法
13676+
13677+ 参数:cron,cron表达式有7个域,每个域之间用空格隔开,7个域分别是:秒 分钟 小时 日 月 星期 年
13678+
13679+ 注:[ 年] 不是必须的域,可以省略[ 年] ,则一共6个域
13680+
13681+ <img src =" https://gitee.com/seazean/images/raw/master/Frame/SpringBoot-Scheduled注解cron参数.jpg " style =" zoom :150% ;" />
13682+
13683+ 例如:
13684+
13685+ * 每隔5秒执行一次:* /5 * * * * ?
13686+ * 每隔5分钟的40秒执行一次:40 * /5 * * * ?
13687+
13688+
13689+
13690+
13691+
1363713692***
1363813693
1363913694
0 commit comments