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 注入

@Autowired
private OrderWorkApplicationService orderWorkApplicationService;
  • 方式二:Setter 方法注入
public class OrderWorkApi {

    private OrderWorkApplicationService orderWorkApplicationService;

    @Autowired
public void setOrderWorkApplicationService(OrderWorkApplicationService orderWorkApplicationService){
this.orderWorkApplicationService = orderWorkApplicationService;
}
}
  • 方式二:Constructor 注入
public class OrderWorkApi {

    private final OrderWorkApplicationService orderWorkApplicationService;

    public OrderWorkApi(final OrderWorkApplicationService orderWorkApplicationService){
this.orderWorkApplicationService = orderWorkApplicationService;
}
}
  • 方式三:Lombok + Constructor 注入

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

Spring AOP(切面编程)

  • 什么是AOP:通过“预编译”或“运行期动态代理”以垂直维护实现程序功能的一种技术。
  • 用途:提供了声明式的企业服务、替代了EJB的服务声明,允许自定义,以完成OOP(面向对象编程)AOP的互补使用。
  • 实现:不是为了提供最完整的AOP实现、而是侧重于提供一种AOP实现与Spring IoC容器之间的整合,用于解决常见的问题(日志、事务、异常)。
    • 预编译:AspectJ
    • 运行期动态代理(jdk动态代理、CGLib动态代理):Spring AOP、Jboss AOP
      • 区别:CGLib动态代理无接口、jdk动态代理有接口。
  • 例子
package com.gdbyway.bpg.ip.nis.aop;

import com.gdbyway.bpg.ip.nis.annotations.TestSoul;
import com.gdbyway.bpg.ip.nis.application.service.diagnosis.DiagnosisApplicationService;
import com.gdbyway.bpg.ip.nis.types.diagnosis.representation.PatHistoryDiagRepresentation;
import com.gdbyway.bpg.ip.nis.types.discharge.query.CommonPatHistoryDiagQuery;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import java.util.List; @Aspect
@Configuration
public class TestSoulAspect { @Autowired
private DiagnosisApplicationService applicationService; //对使用@TestSoul注解作为切入点
@Pointcut("@annotation(com.gdbyway.bpg.ip.nis.annotations.TestSoul)")
public void pointcut() {
} //对使用@TestSoul注解作为切入点
@Before("pointcut()")
public void before(JoinPoint joinPoint) { TestSoul testSoul = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(TestSoul.class);
System.out.println("----------------------myAsp-------------------------------------------------");
CommonPatHistoryDiagQuery query = new CommonPatHistoryDiagQuery();
query.setPatId("96187");
List<PatHistoryDiagRepresentation> ss = applicationService.findByPatId(query);
System.out.println(ss);
}
//返回时处理
@AfterReturning(value = "pointcut()")
public void afterReturning() {
}
//异常时处理
@AfterThrowing(pointcut = "pointcut()",throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
}
}

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提供了两种事务管理机制:编程式事务声明式事务

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

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

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

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

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

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

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

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

获取Spring Bean

  • 特殊场景获取Bean方式(定时任务):ApplicationContextAware
@Component
public class ApplicationServiceFactory implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationServiceFactory.applicationContext = applicationContext;
} public static <T> T getBean(Class<T> clazz) {
if (Objects.isNull(applicationContext)) {
throw new NullPointerException("Spring ApplicationContext is Null");
}
return applicationContext.getBean(clazz);
} public static ApplicationContext getApplicationContext(){
return applicationContext;
} }

获取接口的所有实现类

  • InitializingBean
@Component
public class ApplicationServiceFactory implements InitializingBean {
@Override
public void afterPropertiesSet() { }
}

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. Origin2017、Origin2018详细安装教程

    1.Origin2017安装 1.1 安装步骤: 解压安装包,打开"Origin2017"目录,双击"setup.exe"开始安装 安装步骤1,点击[下一步] ...

  2. LyScript 插件实现UPX寻找入口

    LyScript 插件可实现对压缩壳的快速脱壳操作,目前支持两种脱壳方式,一种是运用API接口自己编写脱壳过程,另一种是直接加载现有的脱壳脚本运行脱壳. 插件地址:https://github.com ...

  3. CE修改器入门:查找共享代码

    本关我们将学习共享代码,在C语言中角色属性都是以结构体的方式进行存储的,而结构体所存储的信息都是连续性的,这一关我们将会解释如何处理游戏中的共用代码,这种代码是通用在除了自己以外的其他同类型对像上的 ...

  4. yarn常用命令

    1. 安装 npm install yarn -g 2. 设置淘宝镜像 yarn config set npmRegistryServer https://registry.npm.taobao.or ...

  5. Python下的三维建模和可视化

    本文介绍基于AnyCAD Rapid Py三维图形平台开发Python的三维应用 1 准备工作 1.1 安装 vc_resit 2022 在Windows下,AnyCAD Rapid SDK依赖Vis ...

  6. Intel 4工艺太难了!酷睿Ultra终于突破5GHz

    无论是14nm还是10nm,Intel这些年的新工艺都有一个通性:刚诞生的时候性能平平,高频率都上不去,只能用于笔记本移动端(分别对应5代酷睿.10代酷睿),后期才不断成熟,比如到了13代酷睿就达到史 ...

  7. 揭秘C语言的心脏:深入探索指针与数组的奥秘

    欢迎大家来到贝蒂大讲堂 养成好习惯,先赞后看哦~ 所属专栏:C语言学习 贝蒂的主页:Betty's blog 1. strlen()和sizeof的区别 名称 区别 sizeof 1. sizeof是 ...

  8. .NET Core开发实战(第1课:课程介绍)--学习笔记

    01 | 课程介绍 讲师介绍 肖伟宇,校宝在线架构师.SkyWalking .NET探针贡献者.NetCorePal组件库创建者 为什么要学习 .NET Core 微软大力支持推动 .Net 技术生态 ...

  9. NC51097 Parity game

    题目链接 题目 题目描述 Now and then you play the following game with your friend. Your friend writes down a se ...

  10. NC16696 [NOIP2001]统计单词个数

    题目链接 题目 题目描述 给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个).要求将此字母串分成k份( 1 < k ≤ 40 ...