Spring

分层解耦

  • 内聚:软件中各个功能模块内部的功能联系。
  • 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
  • 软件设计原则:高内聚低耦合。

三层架构

  • controller:表现层,接收前端发送的请求,对请求进行处理,并响应数据。
  • service:业务逻辑层,处理具体的业务逻辑。
  • dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、删、改、查。

控制反转

  • 控制反转:Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(IOC容器),这种思想称为控制反转(使用对象时,由主动new产生对象转换为由外部提供对象)。
  • 加上@Component注解,即可将当前类交给IOC容器管理,成为IOC容器中的bean
  • @Componnent的衍生注解,因为@Component往往不会用在三层架构上。
    • @Controller:标注在控制器类(Controller层)上
    • @Service::标注在业务类(Service层)上
    • @Repository:标注在数据访问类上(Dao层)上
  • 注意
    • 使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器(Controller层)bean只能用@Controller。因为Controller层的@RestController=@Controller+@ResponseBody。

依赖注入

  • 依赖注入:Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。

    • 加上@Autowired注解,运行时,IOC容器会提供该类型的bean对象,并赋值给该变量–依赖注入
  • @Autowired注解,默认是按照类型进行,如果存在多个相同类型的bean,将会报错误,解决方案

    • @Primary注解:在对应的bean类上加上,即可指定优先级更高
    • @Qualifier注解:通过@Autowired注解和@Qualifier注解(“指定bean名”)指定注入哪个bean
    • @Resource注解 :不用@Autowired注解而是改成@Resource注解(name=“指定bean名”)

Bean

  • Bean对象:IOC容器中创建、管理的对象,称之为bean。
  • Bean组件扫描
    • 默认扫描的范围是启动类所在包及其子包。
  • 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写。
  • 主动获取bean,通过AplicationContext IOC容器对象中的方法
    • 根据名称获取:Object getBean(String name)
    • 根据类型获取:<T> T getBean(Class<T> requiredType)
    • 根据名称和类型获取:<T> T getBean(String name , Class<T> requiredType)

bean作用域

  • 可以通过@Scope(“作用域”)来配置作用域

    • singletion:容器内同名称的bean只有一个实例(单例)(默认)

    • prototype:每次使用该bean时会创建新的实例(非单例)

    • request:每个请求范围内会创建新的实例(web环境中,了解)

    • session:每个会话范围内会创建新的实例(web环境中,了解)

    • application:每个应用范围内会创建新的实例( web环境中,了解)

  • 注意

    • 默认singleton的bean,在容器启动时被创建,可以使用@Lazy注解来延迟初始化(延迟到第一次使用时)。
    • prototype的bean,每一次使用该bean的时候都会创建一个新的实例。
    • 实际开发当中,绝大部分的Bean是单例的,也就是说绝大部分Bean不需要配置scope属性。

第三方bean

  • 如果要管理的bean对象来自于第三方(不是自定义的),是无法用@Component及衍生注解声明bean的,就需要用到@Bean注解。
    • @Bean是加在方法上的,不是类名上
  • 若要管理的第三方bean对象,建议对这些bean进行集中分类配置,可以通过@Configuration注解声明一个配置类。
  • 通过@Bean注解的name或value属性可以声明bean的名称,如果不指定,默认bean的名称就是方法名。
  • 如果第三方bean需要依赖其它bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配。

AOP

AOP基本概念

什么是AOP

  • AOP就是面向切面编程,其实就是面向特定方法编程。

作用

  • 利用AOP可以对业务逻辑的各个部分进行隔离,从而是的业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
  • 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能

使用场景

  • 记录操作日志、权限控制、事务管理等

实现原理

  • 动态代理是面向切面编程最主流的实现。而SpringAOP是Spring框架的高级技术,旨在管理bean对象的过程中,主要通过底层的动态代理机制,对特定的方法进行编程。

专业术语

  • 切入点:PointCut,被AOP控制的匹配连接点的条件,通知仅会在切入点方法执行时被应用
  • 连接点:JoinPoint,可以被AOP控制的方法。
  • 通知:Advice,指哪些重复的逻辑,也就是共性功能,切面必须要完成的工作。(最终体现为一个方法)
  • 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
  • 目标对象:Target,通知所应用的对象
  • AOP最终执行的并非是原始的目标对象,而是基于目标对象自动生成的代理对象。
  • 拿切西瓜来说
    • 连接点就是西瓜的任何地方
    • 切入点表达式就是切西瓜的规则(例如只在西瓜的中间切)
    • 切入点是真正被切的地方
    • 通知是切西瓜前后的动作,比如切西瓜前的拿刀、切西瓜后的放刀。
    • 切面可以是切西瓜的整个过程

通知方法

  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行
    • @Around环绕通知需要自己调用ProceedingJoinPoint.proceed()来让原始方法执行,其他通知不需要考虑目标方法执行
    • @Around环绕通知方法的返回值,必须指定为0bject,来接收原始方法的返回值。
  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行
  • @After:后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执
  • @AfterReturning:返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执
  • @AfterThrowing:异常后通知,此注解标注的通知方法发生异常后执行

步骤

  1. 导入AOP依赖
  2. 定义通知类@Aspect,并将该类交给IOC容器管理(@Component)
  3. 定义通知方法(方法里面实现共性功能)
  4. 定义切入点@Pointcut(切入点表达式)和其依托的方法(切入点定义依托一个不具有实际意义的方法进行,即无参数,无返回值,方法体无实际逻辑)
  5. 绑定切入点与通知关系,并指定通知添加到原始连接点的具体执行位置(通知方法)
    • 切入点表达式可以写在通知方法里面,这样第四步就可以省略了
  6. 开启Spring对AOP注解驱动支持(@EnableAspectJAutoProxy)
    • 在springboot项目里面,可以省略第六步

通知顺序

  • 当有多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被执行。

执行顺序

  1. 不同切面类中,默认按照切面类的类名字母排序:
    • 目标方法前的通知方法:字母排名靠前的先执行
    • 目标方法后的通知方法:字母排名靠前的后执行
  2. 用@Order(数字)加在切面类上来控制顺序
    • 目标方法前的通知方法:数字小的先执行
    • 目标方法后的通知方法:数字小的后执行

切入点表达式

  • 切入点表达式:描述切入点方法的一种表达式
  • 作用:主要用来决定项目中的哪些方法需要加入通知

execution

  • execution主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配
  • 语法:execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数的全类名) 异常?)
  • 其中带?的部分可以省略
  • 注意,异常是方法上声明抛出的异常,不是实际抛出的异常
  • 通配符
    • *:单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分
    • ..:多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数
  • 根据业务需要,可以使用且(&&)、或()、非(!)来组合比较复杂的切入点表达式。

@annotation

  • @annotation切入点表达式,用于匹配标识有特定注解的方法。
  • 特定注解是自己定义的
  • 语法:@annotation(注解全类名)

事务管理

  • 概念:事务是一组操作的集合,它是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败。
  • 操作
    • 开启事务(一组操作开始前,开启事务) : start transaction / begin ;
    • 提交事务(这组操作全部成功后,提交事务): commit ;
    • 回滚事务(中间任何一个操作出现异常,回滚事务) : rollback ;

spring事务管理

  • 注解:@Transactional

    • 位置:业务( service)层的方法上、类上、接口上
    • 作用∶将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务
    • 注意
      • 默认情况下,只有出现RuntimeException 才回滚异常.
  • spring事务管理日志开关

    1
    2
    3
    4
    #开启spring事务管理日志开关
    logging:
    level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug
  • @Transactional的属性

    • rollbackFor:用于控制出现何种异常类型,回滚事务。
      • 如:@Transactional(rollbackFor = Exception.class),所有异常都会回滚事务
    • propagation:可以控制事务的传播行为,其常用属性值如下
      • REQUIRED:【默认值】需要事务,有则加入,无则创建新事务
      • REQUIRES_NEW:需要新事务,无论有无,总是创建新事务