关于Spring的那些事
发布日期:2021-10-06 02:38:22 浏览次数:5 分类:技术文章

本文共 3432 字,大约阅读时间需要 11 分钟。

IOC,AOP的概念以及在项目中的用法?

IOC(控制反转):两种实现(依赖查找(DL) && 依赖注入(DI))

DL:已经被抛弃,因为他需要用户自己去是使用 API 进行查找资源和组装对象。即有侵入性。

DI:是依赖注入,降低模块间的耦合度,不需要new,根据配置文件,用Java反射来创建对象

三种注入方式:

由构造器Constructor 注入、setter方法注入,根据注解注入的方式

 

对于IOC而言,最重要的就是容器,容器管理者Bean的生命周期,控制着Bean的依赖注入。

Spring提供了两种容器----BeanFactory && applicationContext

  --BeanFactory 粗暴简单,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。通常只提供注册(put),获取(get)这两个功能。我们可以称之为 “低级容器”。

  --ApplicationContext 可以称之为 “高级容器”。因为他比 BeanFactory 多了更多的功能。他继承了多个接口。因此具备了更多的功能。在容器启动时,一次性创建所有的bean,这样能及早发现错误。

由于不需要Bean,所以可以面向接口编程

注意:

Java 使用 DI 方式实现 IoC 的不止 Spring,包括 Google 的 Guice,还有一个冷门的 PicoContainer(极度轻量,但只提供 IoC)。

 

AOP(面向切面编程):内部实现动态代理

主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。   

主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改 变这些行为的时候不影响业务逻辑的代码。

AOP是能够让我们在不影响原有功能的前提下,为软件横向扩展功能。

横向扩展:在WEB项目开发中,通常都遵守三层原则,包括控制层(Controller)->业务层(Service)->数据层(dao),那么从这个结构下来的为纵向,它具体的某一层就是我们所说的横向。AOP就是可以作用于这某一个横向模块当中的所有方法。

AOP和OOP的区别:AOP是OOP的补充,当我们需要为多个对象引入一个公共行为,比如日志,操作记录等,就需要在每个对象中引用公共行为,这样程序就产生了大量的重复代码,使用AOP可以完美解决这个问题。

切面(@Aspect):拦截器类,其中会定义切点以及通知

切点:具体拦截的某个业务点。

通知:切面当中的方法,声明通知方法在目标业务层的执行位置,通知类型如下:

  • 前置通知:@Before 在目标业务方法执行之前执行
  • 后置通知:@After 在目标业务方法执行之后执行
  • 返回通知:@AfterReturning 在目标业务方法返回结果之后执行
  • 异常通知:@AfterThrowing 在目标业务方法抛出异常之后
  • 环绕通知:@Around 功能强大,可代替以上四种通知,还可以控制目标业务方法是否执行以及何时执行

比较常用的是:前后、后置和环绕

在项目中的用法:调用每个方法之后,想调用输出日志的方法,那么就能用AOP关联两者,关联是通过注解或者配置文件实现,代码层面则不需要改动。若要修改输出日志模块内容,其他方法不需要改动。

 

你用过哪些Spring注解?尤其是@Autowired?

提到Spring注解,首先就是@Autowired --默认是byType,如果找到多个实现类就会byName, 找不到会报错。

如果有多个实现类,用@Qualifier来指定

 

Bean的生命周期?

1.实例化bean对象,并根据配置,设置其中的properties属性;

2.如果实现了BeanNameAware或者BeanFactoryAware,调用相关方法(一般不实现)

3.如果bean实现了InitializingBean,则调用相关方法

4.调用<bean  init-method= "" >,执行初始化方法

5.如果实现BeanPostProcessor,则执行postprocessAfterInitialization(一般不实现)

6.执行业务本身

7.如果实现了DisposableBean,则调用相关方法(一般不实现)

8.调用<bean destory-method= "" >,执行销毁方法

 

Bean的常见作用域和线程安全性

单例singleton,是默认的,Spring容器内不论多少个请求,都只有一个实例

原型prototype,和单例相反,一个请求产生一个实例

请求request,在一个请求内,将会为每个web请求的客户端创建一个新的实例

大多数bean都是无状态的,比如service和dao的bean,对不同入参请求提供同一类逻辑,所以线程是安全的

保守情况下,不建议用prototype,一方面没有类似需求,另一方面线程是不安全的,需要自己维护

 

Spring实现事物的方式以及事物传播机制的概念?

Spring实现事物的方式: 编程式(和业务代码耦合度高,不建议使用)  && 声明式

可以通过注解实现事务--@Transactional(readOnly=false,propagation = xx,isolation = xx),作用在方法上,表示这个方法里逻辑由事务管理,isolation是事务隔离级别,propagation是事务传播机制

事务传播机制有7种,其中最常见的是PROPAGATION_REQUIRED

(1)PROPAGATION_REQUIRED(默认):如果A有事务则B加入A事务,如果A没有事务则新B建一个事务;

(2)PROPAGATION_NEW:B总是开启一个新的事务,如果A有事务则将A事务挂起先执行B事务;

(3)PROPAGATION_NESTED:RUGU :如果A没事务则新建一个事务,如果A有事务则把B的事务当成A的一个子事务(A事务rolback,commit影响B,B事务rolback,commit不影响A);

(4)PROPAGATION_SUPPORTS:如果A没事务,那就按普通方法执行,如果有A事务则用A的事务(B本身不具备事务);

(5))PROPAGATION_NOT_SUPPORTED:B总是非事务地执行,如果A有事务则把A事务挂起,自己还是以普通方法执行(B本身不具备事务);

(6)PROPAGATION_NEVER:如果A没事务,那就按普通方法执行,如果A有事务则抛出异常((B本身不具备事务);

(7)PROPAGATION_MANDATORY:如果A没事务就抛异常,如果A有事务则使用A的事务(B本身不具备事务);

 

事务的四种级别

(1)READ_UNCOMMITTED(读未提交):,可读取未提交事务的操作数据,这种情况会出现脏读、重复读、幻读问题;

(2)READ_COMMITTED(读提交):一个事务等另一个事务提交之后才可进行读取,解决了脏读问题,但会出现重复读、幻读问题;

(3)REPEATABLE_READ(重复读):读取事务开启的时候不能对数据进行修改,可能出现幻读问题;

(4)SERIALIZABLE (序列化):是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用;

 

脏读

出现原因:修改数据的同时可以读取数据

说明:当事务B对data进行了修改但是未提交事务,此时事务A对data进行读取,并使用事务B修改的数据做业务处理

重复读

出现原因:读取数据的同时可以进行修改

说明:事务A,事务B同时对dataA进行访问,事务A对data进行读取,事务B对data进行修改,当事务A第一次对data进行读取完后事务B提交,此时当事务A第二次读取该数据时的数据就与第一次读取的数据不同,这种情况称为可重复读

幻读

出现原因:读取和修改的时候可以insert数据

说明:data 表有一条数据,事务A对data进行读取, 事务B对data进行数据新增 ,此时事务A读取只有一条数据,而最后实际data是有两条数据,就好象发生了幻觉一样情况成为幻读

 

转载地址:https://blog.csdn.net/luxuiary/article/details/105656146 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:win10下Python 环境安装
下一篇:关于volatile

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月10日 08时58分31秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章