Spring

Spring 是什么?

  • Spring为了解决企业级应用的复杂性而创建,简化开发。
  • 如下简化
    • 基于POJO的轻量级和最小侵入性编程;
    • IoC(控制反转)、DI(依赖注入)和面向接口实现松耦合;
    • 基于AOP(切面编程)和惯性进行声明式编程;
    • 以切面和模版减少样式代码;

Spring IoC(控制反转)

  • IoC 负责创建、维护、并管理对象之间依赖关系的容器。

  • 什么叫控制反转:控制权的转移——应用程序本身负责依赖对象的创建和维护的控制权转移给IoC容器管理。

  • 什么控制被反转:获取依赖对象的过程被反转了——获取依赖对象的过程由自身变为IoC容器主动注入。

  • 为什么要使用IoC:实现对象之间的解耦、复用;

  • 实现方式:DI(依赖注入)、工厂模式。

Spring DI(依赖注入)

  • 什么叫依赖注入:程序在运行时依赖IOC容器来动态注入对象所需的资源;(Java DI官方标准是JSR-330,Guice是一个轻量级的DI框架。)

  • DI是IoC的一种实现方式。

  • 为什么使用DI:松耦合、易测试、强内聚、可重用。

  • 方式一:Field 注入

  1. @Autowired
  2. private OrderWorkApplicationService orderWorkApplicationService;
  • 方式二:Setter 方法注入
  1. public class OrderWorkApi {
  2. private OrderWorkApplicationService orderWorkApplicationService;
  3. @Autowired
  4. public void setOrderWorkApplicationService(OrderWorkApplicationService orderWorkApplicationService){
  5. this.orderWorkApplicationService = orderWorkApplicationService;
  6. }
  7. }
  • 方式二:Constructor 注入
  1. public class OrderWorkApi {
  2. private final OrderWorkApplicationService orderWorkApplicationService;
  3. public OrderWorkApi(final OrderWorkApplicationService orderWorkApplicationService){
  4. this.orderWorkApplicationService = orderWorkApplicationService;
  5. }
  6. }
  • 方式三:Lombok + Constructor 注入

    • 保证依赖的对象不为Null。
    • 避免 Field 注入的循环依赖问题。
  1. @RequiredArgsConstructor
  2. public class OrderWorkApi {
  3. private final OrderWorkApplicationService orderWorkApplicationService;
  4. }

Spring AOP(切面编程)

  • 什么是AOP:通过“预编译”或“运行期动态代理”以垂直维护实现程序功能的一种技术。
  • 用途:提供了声明式的企业服务、替代了EJB的服务声明,允许自定义,以完成OOP(面向对象编程)AOP的互补使用。
  • 实现:不是为了提供最完整的AOP实现、而是侧重于提供一种AOP实现与Spring IoC容器之间的整合,用于解决常见的问题(日志、事务、异常)。
    • 预编译:AspectJ
    • 运行期动态代理(jdk动态代理、CGLib动态代理):Spring AOP、Jboss AOP
      • 区别:CGLib动态代理无接口、jdk动态代理有接口。
  • 例子
  1. package com.gdbyway.bpg.ip.nis.aop;
  2. import com.gdbyway.bpg.ip.nis.annotations.TestSoul;
  3. import com.gdbyway.bpg.ip.nis.application.service.diagnosis.DiagnosisApplicationService;
  4. import com.gdbyway.bpg.ip.nis.types.diagnosis.representation.PatHistoryDiagRepresentation;
  5. import com.gdbyway.bpg.ip.nis.types.discharge.query.CommonPatHistoryDiagQuery;
  6. import org.aspectj.lang.JoinPoint;
  7. import org.aspectj.lang.annotation.*;
  8. import org.aspectj.lang.reflect.MethodSignature;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.context.annotation.Configuration;
  11. import java.util.List;
  12. @Aspect
  13. @Configuration
  14. public class TestSoulAspect {
  15. @Autowired
  16. private DiagnosisApplicationService applicationService;
  17. //对使用@TestSoul注解作为切入点
  18. @Pointcut("@annotation(com.gdbyway.bpg.ip.nis.annotations.TestSoul)")
  19. public void pointcut() {
  20. }
  21. //对使用@TestSoul注解作为切入点
  22. @Before("pointcut()")
  23. public void before(JoinPoint joinPoint) {
  24. TestSoul testSoul = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(TestSoul.class);
  25. System.out.println("----------------------myAsp-------------------------------------------------");
  26. CommonPatHistoryDiagQuery query = new CommonPatHistoryDiagQuery();
  27. query.setPatId("96187");
  28. List<PatHistoryDiagRepresentation> ss = applicationService.findByPatId(query);
  29. System.out.println(ss);
  30. }
  31. //返回时处理
  32. @AfterReturning(value = "pointcut()")
  33. public void afterReturning() {
  34. }
  35. //异常时处理
  36. @AfterThrowing(pointcut = "pointcut()",throwing = "ex")
  37. public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
  38. }
  39. }

Spring MVC

  • 什么是MVC: 一种架构模式、思考方式——程序分层、分工合作、既相互独立又协同工作。
  • M(模型层):展示信息
  • V(视图层):界面布局
  • C(控制层):处理业务逻辑

Spring @Async(异步)

  • @Async 可标记在方法上,以便异步调用该方法。调用者将在调用时立即返回,方法的实际执行将提交给SringTaskExecutor的任务中,由指定的线程池中的线程执行!

  • 实际应用中:推荐使用自定义线程池模式(自定义线程池常用方案:重新实现接口AsyncConfigurer)

  • 应用场景

    • 同步:整个操作流程依次执行,每个过程执行完毕、并返回结果!

    • 异步:异步调用只是发送调用的指令,调用者无需等待被调用的方法完全执行完毕,而是继续执行之后的流程!

      注意:Java一般基于创建独立的线程完相应的异步调用逻辑,通过主线程和业务子线程之间执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。

  • Spring 的线程池

    • SimpleAsyncTaskExecutor:默认每次调用都创建新的线程,不重用线程、并非真正的线程池!
    • SyncTaskExecutor:同步操作,没有实现异步调用,适用于不需要多线程的地方!
    • ConcurrentTaskExecutorThreadPoolTaskExecutor不被满足时,可以考虑使用!
    • SimpleThreadPoolTaskExecutor:线程池同时被Quartz和非Quartz使用,才需要使用此类!
    • ThreadPoolTaskExecutor:最常用。
  • @Async默认:SimpleAsyncTaskExecutor

  • 自定义线程池方式

    • 实现接口AsyncConfigurer
    • 继承AsyncConfigurerSupport
    • 配置自定义的TaskExecutor

Spring @Transactional(事务)

  • Spring提供了两种事务管理机制:编程式事务声明式事务

  • 编程式事务:是指在代码中手动的管理事务的提交、回滚等操作,代码侵入性比较强。

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.jdbc.core.JdbcTemplate;
  3. import org.springframework.transaction.PlatformTransactionManager;
  4. import org.springframework.transaction.TransactionStatus;
  5. import org.springframework.transaction.support.DefaultTransactionDefinition;
  6. public class MyService {
  7. private final JdbcTemplate jdbcTemplate;
  8. private final PlatformTransactionManager transactionManager;
  9. @Autowired
  10. public MyService(JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager) {
  11. this.jdbcTemplate = jdbcTemplate;
  12. this.transactionManager = transactionManager;
  13. }
  14. public void performTransactionalOperation() {
  15. DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  16. TransactionStatus status = transactionManager.getTransaction(def);
  17. try {
  18. // 执行数据库操作,例如:
  19. jdbcTemplate.update("INSERT INTO my_table (name) VALUES ('John Doe')");
  20. jdbcTemplate.update("UPDATE another_table SET count = count + 1 WHERE id = ?", 1);
  21. // 如果没有异常,提交事务
  22. transactionManager.commit(status);
  23. } catch (Exception ex) {
  24. // 如果发生异常,回滚事务
  25. transactionManager.rollback(status);
  26. throw ex; // 可以选择重新抛出异常或进行其他处理
  27. }
  28. }
  29. }
  • 声明式事务:基于AOP面向切面使业务和事务解耦,代码侵入性比较低。
  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.jdbc.core.JdbcTemplate;
  3. import org.springframework.stereotype.Service;
  4. import org.springframework.transaction.annotation.Transactional;
  5. @Service
  6. public class MyService {
  7. private final JdbcTemplate jdbcTemplate;
  8. @Autowired
  9. public MyService(JdbcTemplate jdbcTemplate) {
  10. this.jdbcTemplate = jdbcTemplate;
  11. }
  12. @Transactional(rollbackFor = Exception.class)
  13. public void performTransactionalOperation() {
  14. // 执行数据库操作,例如:
  15. jdbcTemplate.update("INSERT INTO my_table (name) VALUES ('John Doe')");
  16. jdbcTemplate.update("UPDATE another_table SET count = count + 1 WHERE id = ?", 1);
  17. // 如果以上操作成功,事务将自动提交;如果发生异常,事务将自动回滚
  18. // 也可以手动设置回滚
  19. // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  20. }
  21. }
  • 常见@Transactional声明式事务的失效场景

    • 事务方法内部捕捉了异常,但没有抛出:如果事务方法内部捕获了异常且没有重新抛出,那么Spring事务管理器不会感知到异常,因此不会触发事务回滚。为了确保事务能够正常回滚,应该让异常冒泡到方法外部。

    • 同一个类中方法调用/this调用:如果在一个类中,一个方法调用了同一个类的另一个被 @Transactional 注解的方法,那么被调用的方法的事务注解将不会生效。这是因为 Spring 的 AOP 代理通常只会在不同类的方法调用时生效。this 引用的是当前类的实例,而不是 Spring 代理的实例,因此事务增强不会应用。如下为其中一种解决方案:

      1. import org.springframework.aop.framework.AopContext;
      2. import org.springframework.beans.factory.annotation.Autowired;
      3. import org.springframework.context.annotation.EnableAspectJAutoProxy;
      4. import org.springframework.jdbc.core.JdbcTemplate;
      5. import org.springframework.stereotype.Service;
      6. import org.springframework.transaction.annotation.Transactional;
      7. //
      8. @Service
      9. @EnableAspectJAutoProxy(exposeProxy = true)
      10. public class MyService {
      11. private final JdbcTemplate jdbcTemplate;
      12. @Autowired
      13. public MyService(JdbcTemplate jdbcTemplate) {
      14. this.jdbcTemplate = jdbcTemplate;
      15. }
      16. // 改为动态代理调用,而非直接调用
      17. public void insertBusiness(){
      18. MyService impl = (MyService) AopContext.currentProxy();
      19. impl.insert();
      20. }
      21. @Transactional(rollbackFor = Exception.class)
      22. public void insert(){
      23. jdbcTemplate.update("INSERT INTO my_table (name) VALUES ('John Doe')");
      24. jdbcTemplate.update("UPDATE another_table SET count = count + 1 WHERE id = ?", 1);
      25. }
      26. }
    • 方法可见性:如果 @Transactional 注解被应用于一个非 public 方法(如 protectedprivate 或默认包可见性),虽然不会报错,但事务设置将不会起作用。@Transactional 注解应该只应用于 public 方法,因为 Spring AOP 代理通常是通过代理对象来调用目标方法的,而代理对象只能调用 public 方法。

    • 数据库引擎不支持事务:如果使用的数据库引擎不支持事务(例如,MyISAM 存储引擎在 MySQL 中不支持事务),那么即使使用了 @Transactional 注解,事务也不会生效。

    • 异常类型:Spring 默认只会对运行时异常(RuntimeException 及其子类)进行事务回滚。如果方法抛出了检查异常(即非运行时异常),并且没有被捕获处理,事务也不会回滚。可以通过在 @Transactional 注解中设置 rollbackFor 属性来指定需要回滚的异常类型。

    • 事务传播行为设置不当@Transactional 注解中的 propagation 属性用于设置事务的传播行为。如果传播行为设置不当,可能会导致事务不按照预期工作。例如,TransactionDefinition.PROPAGATION_NEVER 表示以非事务方式运行,如果当前存在事务,则抛出异常。

获取Spring Bean

  • 特殊场景获取Bean方式(定时任务):ApplicationContextAware
  1. @Component
  2. public class ApplicationServiceFactory implements ApplicationContextAware {
  3. private static ApplicationContext applicationContext;
  4. @Override
  5. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  6. ApplicationServiceFactory.applicationContext = applicationContext;
  7. }
  8. public static <T> T getBean(Class<T> clazz) {
  9. if (Objects.isNull(applicationContext)) {
  10. throw new NullPointerException("Spring ApplicationContext is Null");
  11. }
  12. return applicationContext.getBean(clazz);
  13. }
  14. public static ApplicationContext getApplicationContext(){
  15. return applicationContext;
  16. }
  17. }

获取接口的所有实现类

  • InitializingBean
  1. @Component
  2. public class ApplicationServiceFactory implements InitializingBean {
  3. @Override
  4. public void afterPropertiesSet() {
  5. }
  6. }

Spring 知识点的更多相关文章

  1. Spring知识点回顾(08)spring aware

    Spring知识点回顾(08)spring aware BeanNameAware 获得容器中的bean名称 BeanFactoryAware 获得当前的bean factory Applicatio ...

  2. Spring知识点回顾(07)事件发布和监听

    Spring知识点回顾(07)事件发布和监听 1.DemoEvent extends ApplicationEvent { public DemoEvent(Object source, String ...

  3. Spring知识点回顾(01)Java Config

    Spring知识点回顾(01) 一.Java Config 1.服务和服务注入 2.Java 注解 :功能更强一些 3.测试验证 二.注解注入 1.服务和服务注入 2.配置加载 3.测试验证 三.总结 ...

  4. Spring知识点复习

    Spring知识点复习 一.专业术语 侵入式设计 引入框架,对现有的类的结构有影响,即需要实现或继承某些特定类.如:Struts框架 非侵入式设计 引入框架,对现有的类结构没有影响.如:Hiberna ...

  5. <转>Spring 知识点提炼

    Spring 知识点提炼 1. Spring框架的作用 轻量:Spring是轻量级的,基本的版本大小为2MB 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依 ...

  6. Spring知识点总结(三)之注解方式实现IOC和DI

        1. 注解概念        所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式.        关于注解的知识点,参看java基础课程中java基础加强部分的内容.    2 ...

  7. Spring知识点提炼

    原文出处: 朱小厮 1. Spring框架的作用 轻量:Spring是轻量级的,基本的版本大小为2MB 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对 ...

  8. Spring知识点总结大全(2)

    3.Spring的AOP 一.AOP(Aspect-oriented programming,面向切面编程): 什么是AOP? 定义:将程序中的交叉业务逻辑提取出来,称之为切面.将这些切面动态织入到目 ...

  9. Spring知识点总结大全(1)

    1.Spring的分层结构 1.Presentation layer(表示层) (1) 表示逻辑(生成界面代码) (2) 接收请求 (3) 处理业务层抛出的异常 (4) 负责规则验证(数据格式,数据非 ...

  10. Spring知识点总结

    1.1 什么是Spring Spring是分层的JavaSE/EE full-stack(一站式)轻量级开源框架,以IoC(Inverse of Control 反转控制)和AOP(Aspect Or ...

随机推荐

  1. 【4】 VScode最全面最实用的插件推荐,用了你就爱上了!

    相关文章: [一]tensorflow安装.常用python镜像源.tensorflow 深度学习强化学习教学 [二]tensorflow调试报错.tensorflow 深度学习强化学习教学 [三]t ...

  2. 监控Celery不一定非要使用Flower

    运维平台中有许多的周期/定时/异步任务,例如证书扫描.数据备份.日志清理.线上作业等等,这些任务的执行都是借助于Celery来完成的.任务多了之后就会遇到一系列的问题,例如我之前写过的将任务分多队列来 ...

  3. docker容器-乌班图安装vim

    apt-get update && apt-get install -y vim

  4. 【Java并发入门】01 并发编程Bug的源头

    一.根本原因 「CPU.内存.磁盘之间的速度差异」 为了能同时执行多个任务,CPU 发展出时间片轮转.多核等 CPU 要从内存中读数据太慢了,所以给自己设置了缓存 CPU 读磁盘更慢了,所以可以让该线 ...

  5. 《ASP.ENT Core 与 RESTful API 开发实战》-- (第5章)-- 读书笔记(上)

    第 5 章 使用 Entity Framework Core 5.1 Entity Framework Core EF Core 是微软推出的 ORM 框架,一种为了解决高级编程语言中的对象和关系型数 ...

  6. 编译pjsip源码

    操作系统 : Windows 10_x64 [版本 10.0.19042.685] pjsip版本 : 2.10 pjsip官网:https://www.pjsip.org/ 1. 下载pjsip源代 ...

  7. 多个request接口的功能优化处理速度

    一.原始代码功能如下,包含两个request接口的调用,耗时情况约4秒 import datetime import time import requests start_time = datetim ...

  8. 【译】我为 .NET 开发人员准备的 2023 年 Visual Studio 10 大新功能

    原文 | James Montemagno 翻译 | 郑子铭 Visual Studio 2022 在 2023 年发布了许多令人难以置信的功能,为 .NET 开发人员提供了大量新工具来提高他们的工作 ...

  9. Power BI 11 DAY

    目录 电商平台流量分析 流量相关指标 流量数量指标 流量质量指标 度量值计算公式 流量转化率重要指标 指标观测维度 电商平台流量分析 电商平台黄金公式:销售额 = 流量 + 转化率 + 客单价 流量相 ...

  10. NC17315 背包

    题目链接 题目 题目描述 Applese有 \(1\) 个容量为 \(v\) 的背包,有 \(n\) 个物品,每一个物品有一个价值 \(a_i\) ,以及一个大小 \(b_i\) 然后他对此提出了自己 ...