本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!