乐趣区

关于程序员:Spring现代Java开发的必备框架

[TOC]

Spring:古代 Java 开发的必备框架

Spring 是一个轻量级的 Java 框架,它提供了各种企业级利用程序开发的工具和技术。Spring 框架的外围是 IoC 容器和 AOP 框架。IoC 容器使得 Java 应用程序的组件化变得更加容易,AOP 框架使得 Java 应用程序的切面编程变得更加容易。Spring 框架还提供了许多其余的性能,例如数据拜访、Web 开发、安全性、事务管理等。

Spring 创立 bean 的生命周期以及对应的接口和注解

Spring 创立 bean 的生命周期蕴含以下步骤:

  1. 实例化 Bean:Spring 通过结构器或工厂办法来创立 Bean 实例。
  2. 设置 Bean 属性:Spring 通过 setter 办法或间接拜访字段来设置 Bean 的属性值。
  3. BeanNameAware 接口:如果 Bean 实现了 BeanNameAware 接口,Spring 将 Bean 的 ID 传递给 setBeanName() 办法。
  4. BeanFactoryAware 接口:如果 Bean 实现了 BeanFactoryAware 接口,Spring 将 BeanFactory 实例传递给 setBeanFactory() 办法。
  5. ApplicationContextAware 接口:如果 Bean 实现了 ApplicationContextAware 接口,Spring 将 ApplicationContext 实例传递给 setApplicationContext() 办法。
  6. Pre-Initialization BeanPostProcessor:在 Bean 初始化之前,Spring 通过调用 PostProcessBeforeInitialization() 办法提供了一个扩大点,能够在 Bean 初始化之前对 Bean 进行定制。
  7. InitializingBean 接口:如果 Bean 实现了 InitializingBean 接口,Spring 将调用 afterPropertiesSet() 办法。
  8. 自定义初始化办法:Bean 能够自定义初始化办法,只须要在 Bean 定义中指定该办法的名称。
  9. Post-Initialization BeanPostProcessor:在 Bean 初始化之后,Spring 通过调用 PostProcessAfterInitialization() 办法提供了一个扩大点,能够在 Bean 初始化之后对 Bean 进行定制。
  10. DisposableBean 接口:如果 Bean 实现了 DisposableBean 接口,Spring 将调用 destroy() 办法。
  11. 自定义销毁办法:Bean 能够自定义销毁办法,只须要在 Bean 定义中指定该办法的名称。

在 Spring 中,能够应用以下注解来管制 Bean 的生命周期:

  • @PostConstruct:指定初始化办法,相当于 InitializingBean 接口的 afterPropertiesSet() 办法。
  • @PreDestroy:指定销毁办法,相当于 DisposableBean 接口的 destroy() 办法。
  • @Bean(initMethod = “initMethod”, destroyMethod = “destroyMethod”):指定初始化办法和销毁办法。

Spring 应用三级缓存解决循环依赖的原理

  1. singletonObjects:保留曾经齐全创立好的单例 Bean。
  2. earlySingletonObjects:保留曾经实例化、然而还未填充属性的单例 Bean。
  3. singletonFactories:保留 Bean 的工厂办法。

当两个 Bean 相互依赖时,Spring 会先应用工厂办法创立一个 Bean 的代理对象,而后将代理对象放入到 singletonFactories 缓存中。接着,Spring 会持续创立被依赖的 Bean。如果创立被依赖的 Bean 时,须要援用到代理对象,Spring 会先到 singletonFactories 缓存中查找代理对象,如果找到了,就应用代理对象,否则就持续创立代理对象。当被依赖的 Bean 创立实现后,Spring 会将被依赖的 Bean 放入到 singletonObjects 缓存中。接着,Spring 会回到代理对象,填充代理对象的属性,而后将代理对象放入到 earlySingletonObjects 缓存中。当代理对象的属性填充实现后,Spring 会将代理对象替换成真正的 Bean 对象,而后将真正的 Bean 对象放入到 singletonObjects 缓存中,并革除 earlySingletonObjects 缓存和 singletonFactories 缓存中的代理对象。

Spring 应用三级缓存创立 bean 的过程

Spring 应用三级缓存创立 Bean 的具体过程如下:

  1. 首先,Spring 会查看该 Bean 是否曾经创立并存储在 singletonObjects 缓存中。如果 Bean 曾经存在,则间接返回该 Bean 实例。这是最快的状况。
  2. 如果 Bean 不存在于 singletonObjects 缓存中,Spring 会查看该 Bean 是否正在创立中。如果正在创立中,则返回一个代理对象,该代理对象会在真正的 Bean 创立实现后被替换成真正的 Bean 对象。这是为了避免循环依赖的状况。
  3. 如果该 Bean 既不存在于 singletonObjects 缓存中,也没有正在创立中,则 Spring 会创立一个 ObjectFactory,该 ObjectFactory 负责创立该 Bean 实例。ObjectFactory 是一个工厂办法,它负责创立和返回 Bean 实例。
  4. 而后,Spring 会将该 ObjectFactory 存储到 singletonFactories 缓存中,以便下次获取该 Bean 实例时应用。这是为了进步创立 Bean 实例的效率。
  5. 接着,Spring 会查看该 Bean 是否依赖于其余 Bean。如果依赖于其余 Bean,则会先创立依赖的 Bean 实例。依赖项能够是其余 Bean,也能够是根本类型或汇合。
  6. 如果依赖的 Bean 实例还不存在,则 Spring 会递归地创立依赖的 Bean 实例,直到所有依赖的 Bean 实例都曾经创立实现。这是为了保障依赖关系正确。
  7. 如果所有依赖的 Bean 实例都曾经创立实现,则 Spring 会从 singletonFactories 缓存中获取该 Bean 的 ObjectFactory,并应用该 ObjectFactory 创立该 Bean 实例。这是 Bean 实例的创立过程。
  8. 创立该 Bean 实例后,Spring 会将该 Bean 实例存储到 earlySingletonObjects 缓存中,以便后续填充该 Bean 的属性。earlySingletonObjects 缓存蕴含曾经创立的单例 Bean 实例,然而还没有填充属性。
  9. 接着,Spring 会递归地填充该 Bean 的属性。如果该 Bean 的属性依赖于其余 Bean,则会先创立依赖的 Bean 实例。填充属性之前,Spring 会调用所有实现了 BeanPostProcessor 接口的类的 postProcessBeforeInitialization() 办法做一些预处理工作。这是为了提供一个扩大点,能够在 Bean 初始化之前对 Bean 进行定制。
  10. 如果所有依赖的 Bean 实例都曾经创立实现,则 Spring 会从 singletonObjects 缓存中获取依赖的 Bean 实例,并将依赖的 Bean 实例填充到该 Bean 的属性中。填充属性之后,Spring 会再次调用所有实现了 BeanPostProcessor 接口的类的 postProcessAfterInitialization() 办法做一些后处理工作。这是为了提供一个扩大点,能够在 Bean 初始化之后对 Bean 进行定制。
  11. 填充该 Bean 的属性后,Spring 会将该 Bean 实例存储到 singletonObjects 缓存中,并从 earlySingletonObjects 缓存中移除该 Bean 实例。singletonObjects 缓存蕴含曾经创立的单例 Bean 实例,并曾经填充了属性。
  12. 最初,Spring 会递归地解决该 Bean 的后置处理器,而后返回该 Bean 实例。如果 Bean 实现了 InitializingBean 接口,Spring 会调用其 afterPropertiesSet() 办法,这是 Bean 初始化之后的最初一步。如果 Bean 实现了 DisposableBean 接口,Spring 会在 Bean 销毁之前调用其 destroy() 办法。

Spring 应用 AOP

根本过程如下:

  1. 在配置类上增加 @EnableAspectJAutoProxy 注解,启用 AspectJ 主动代理。
  2. 创立一个切面类,并且在该类上应用 @Aspect 注解来标识该类为切面类。
  3. 在切面类中定义一个或多个切点,用来匹配须要拦挡的办法。
  4. 在切面类中定义一个或多个告诉,用来在办法执行前、执行后或抛出异样时执行一些额定的逻辑。
  5. 将切面类增加到 Spring 的容器中。

以下是一个应用注解形式实现 AOP 的示例:

@Aspect
@Component
public class LoggingAspect {@Pointcut("execution(* com.example.demo.service.*.*(..))")
    public void serviceLayer(){}

    @Before("serviceLayer()")
    public void logBefore(JoinPoint joinPoint) {System.out.println("Before" + joinPoint.getSignature().getName());
    }

    @After("serviceLayer()")
    public void logAfter(JoinPoint joinPoint) {System.out.println("After" + joinPoint.getSignature().getName());
    }
}

@Service
public class DemoService {public void doSomething() {System.out.println("Doing something...");
    }
}

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.example.demo")
public class AppConfig {
}

在下面的示例中,LoggingAspect 是一个切面类,它定义了一个切点 serviceLayer() 和两个告诉 logBefore() 和 logAfter()。serviceLayer() 用来匹配 com.example.demo.service 包中所有办法,logBefore() 和 logAfter() 别离在办法执行前和执行后输入一条日志。DemoService 是一个一般的服务类,它的 doSomething() 办法会被 LoggingAspect 拦挡。最初,AppConfig 是一个配置类,它启用了 AspectJ 主动代理,并将 LoggingAspect 和 DemoService 增加到 Spring 的容器中。

当调用 DemoService 的 doSomething() 办法时,LoggingAspect 会拦挡该办法,并在办法执行前输入一条日志,同时在办法执行后输入一条日志。

SpringAOP 的实现原理

Spring AOP 的实现原理是应用动静代理技术。动静代理是在运行时创立代理对象,代理对象实现了指标对象的接口,并且拦挡所有办法调用。Spring AOP 应用了两种类型的代理:JDK 动静代理和 CGLIB 动静代理。如果指标对象实现了接口,则应用 JDK 动静代理;否则,应用 CGLIB 动静代理。

Spring 应用事务管理

Spring 的事务管理能够通过如下形式来应用:

  1. 配置事务管理器:Spring 提供了多种事务管理器,如 DataSourceTransactionManager、HibernateTransactionManager 等。能够通过配置事务管理器来抉择适宜的事务管理器。
  2. 配置事务属性:能够通过配置事务属性来指定事务的流传行为、隔离级别、超时工夫、只读等个性。
  3. 应用 @Transactional 注解:能够在须要事务管理的办法上增加 @Transactional 注解,Spring 会主动治理该办法的事务。@Transactional 注解能够指定事务的流传行为、隔离级别、超时工夫、只读等个性。

Spring 事务的流传行为指的是当一个事务办法调用另外一个事务办法时,如何治理事务。Spring 定义了七种流传行为,包含:

  • REQUIRED:如果以后存在事务,则退出该事务,否则创立一个新的事务。
  • SUPPORTS:如果以后存在事务,则退出该事务,否则以非事务的形式执行。
  • MANDATORY:必须在一个已有的事务中执行,否则抛出异样。
  • REQUIRES_NEW:创立一个新的事务,并且暂停以后事务(如果存在)。
  • NOT_SUPPORTED:以非事务形式执行操作,如果以后存在事务,则暂停该事务。
  • NEVER:以非事务形式执行操作,如果以后存在事务,则抛出异样。
  • NESTED:如果以后存在事务,则在嵌套事务内执行。如果以后没有事务,则执行 REQUIRED 相似的操作。

Spring 事务的隔离级别指的是多个事务之间的隔离水平。Spring 定义了五种隔离级别,包含:

  • DEFAULT:应用底层数据库的默认隔离级别。
  • READ_UNCOMMITTED:容许脏读、不可反复读和幻读。
  • READ_COMMITTED:禁止脏读,但容许不可反复读和幻读。
  • REPEATABLE_READ:禁止脏读和不可反复读,但容许幻读。
  • SERIALIZABLE:禁止脏读、不可反复读和幻读,最严格的隔离级别。

Spring 事务的超时工夫指的是事务的执行工夫超过该工夫时,事务将被回滚。Spring 默认的事务超时工夫为 -1,示意事务没有超时限度。只读事务指的是事务中只读取数据,不批改数据。只读事务能够进步数据库的并发性能。

能够应用 @Transactional 注解来指定事务的流传行为、隔离级别、超时工夫、只读等个性。例如:

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 3600, readOnly = false)
public void doSomething() {// some code}

在这个例子中,@Transactional 注解指定了事务的流传行为为 REQUIRED、隔离级别为 DEFAULT、超时工夫为 3600 秒、只读为 false。

应用 Spring 事务管理能够进步应用程序的性能和可靠性。它能够确保在事务范畴内的所有操作要么全副胜利,要么全副失败,从而保持数据的完整性和一致性。

Spring 事务的原理

Spring 事务的实现原理是应用 AOP 技术。在 Spring 中,事务管理是通过将事务管理器和事务告诉利用到指标办法上来实现的。事务管理器是负责管理事务的对象,事务告诉是负责在指标办法执行前后开启、提交或回滚事务的对象。在 Spring 中,事务告诉是应用 AspectJ 的 @Aspect 注解来实现的。

当一个办法被标记为 @Transactional 时,Spring 会创立一个代理对象来代理该办法。该代理对象会将指标办法的调用转发给事务告诉。在事务告诉中,会依据事务管理器的配置来开启、提交或回滚事务。如果办法执行过程中产生了异样,则会回滚事务。如果办法执行胜利,则会提交事务。事务管理器会将事务的状态存储在 ThreadLocal 中,以便在同一线程中的其余办法也能够拜访该事务。

Spring 事务的实现依赖于底层的数据库事务。Spring 提供了多种事务管理器,如 DataSourceTransactionManager、HibernateTransactionManager 等。事务管理器能够配置事务的流传行为、隔离级别、超时工夫、只读等个性。

DataSourceTransactionManager 的实现

DataSourceTransactionManager 的实现次要包含以下内容:

  1. 实现了 PlatformTransactionManager 接口,用于治理事务的生命周期。PlatformTransactionManager 接口是 Spring 事务管理器的外围接口,它定义了事务的生命周期和状态转换规则。DataSourceTransactionManager 实现了 PlatformTransactionManager 接口,用于治理基于 DataSource 的事务。PlatformTransactionManager 接口包含以下办法:

    • getTransaction(TransactionDefinition definition):获取一个新的事务或将以后线程中的事务退出到以后办法的事务中。
    • commit(TransactionStatus status):提交以后事务。
    • rollback(TransactionStatus status):回滚以后事务。
  2. 实现了 TransactionDefinition 接口,用于定义事务的流传行为、隔离级别、超时工夫、只读等个性。TransactionDefinition 接口定义了事务的属性,包含流传行为、隔离级别、超时工夫、只读等。DataSourceTransactionManager 实现了 TransactionDefinition 接口,用于指定基于 DataSource 的事务的属性。
  3. 实现了 TransactionStatus 接口,用于跟踪事务的状态。TransactionStatus 接口定义了事务的状态,包含未提交、已提交和已回滚。DataSourceTransactionManager 实现了 TransactionStatus 接口,用于跟踪基于 DataSource 的事务的状态。
  4. 实现了 TransactionSynchronizationManager 类,用于治理事务的同步状态。TransactionSynchronizationManager 类用于治理事务的同步状态,包含事务的开始、完结和回滚等操作。DataSourceTransactionManager 应用 TransactionSynchronizationManager 类来治理基于 DataSource 的事务的同步状态。
  5. 实现了 TransactionAspectSupport 类,用于反对基于 AspectJ 的事务告诉。TransactionAspectSupport 类是 Spring 事务管理的外围类,它实现了基于 AspectJ 的事务告诉逻辑。DataSourceTransactionManager 应用 TransactionAspectSupport 类来反对基于 AspectJ 的事务告诉。

DataSourceTransactionManager 的工作流程

  1. 当一个办法被标记为 @Transactional 时,Spring 会创立一个代理对象来代理该办法。
  2. 代理对象会调用 TransactionAspectSupport 类的 invokeWithinTransaction() 办法,该办法会在事务的上下文中执行指标办法。
  3. 在 invokeWithinTransaction() 办法中,会调用 DataSourceTransactionManager 的 doBegin() 办法来开启事务。
  4. 在 doBegin() 办法中,会获取以后线程中的 Connection 对象,并将其设置为事务的连贯。
  5. 如果以后线程中没有 Connection 对象,则会从 DataSource 中获取一个新的 Connection 对象,并将其设置为事务的连贯。
  6. 如果事务的隔离级别不是默认值,则会将事务的隔离级别设置到 Connection 对象上。
  7. 如果事务的超时工夫不是默认值,则会将事务的超时工夫设置到 Connection 对象上。
  8. 在指标办法执行结束后,会调用 TransactionAspectSupport 类的 invokeWithinTransaction() 办法的 afterCompletion() 办法来提交或回滚事务。
  9. 在 afterCompletion() 办法中,会调用 DataSourceTransactionManager 的 doCleanupAfterCompletion() 办法来清理事务状态。
  10. 在 doCleanupAfterCompletion() 办法中,会将事务的连贯敞开,并将其从以后线程中移除。

Spring 不太罕用的注解

  • @Lazy:指定 Bean 是否提早初始化。默认状况下,Spring 会在容器启动时创立所有的单例 Bean,通过设置 @Lazy 注解能够将 Bean 的创立推延到第一次应用时。这对于那些启动工夫较长的应用程序来说十分有用,能够进步应用程序的启动速度。
  • @DependsOn:指定 Bean 依赖的其余 Bean。如果被依赖的 Bean 未被创立,则会先创立该 Bean。@DependsOn 注解能够用来管制 Bean 的创立程序,确保依赖的 Bean 在以后 Bean 之前被创立。
  • @Primary:在多个 Bean 实现某个接口时,指定默认应用哪个 Bean。当一个接口有多个实现类时,能够应用 @Primary 注解来指定默认应用哪个实现类。如果没有指定 @Primary 注解,则须要应用 @Qualifier 注解来指定应用哪个实现类。
  • @Qualifier:指定应用哪个 Bean 实现某个接口。当有多个 Bean 实现同一个接口时,能够应用 @Qualifier 注解来指定应用哪个 Bean。@Qualifier 注解须要与 @Autowired 注解一起应用,在注入 Bean 时指定应用哪个实现类。
  • @Profile:指定 Bean 在特定的环境中才会被创立。能够应用 @Profile 注解来指定 Bean 在哪些环境下被创立,例如开发环境、测试环境或生产环境。
  • @Value:从属性文件中获取 Bean 的属性值。能够应用 @Value 注解来指定 Bean 的属性值。@Value 注解能够用来注入简略类型的值,例如字符串、数字或布尔值。
  • @RestController:将一个类申明为 RESTful Web 服务的控制器。能够应用 @RestController 注解来将一个类申明为 RESTful Web 服务的控制器,使其可能解决 HTTP 申请并返回 JSON 或 XML 格局的数据。
  • @ExceptionHandler:解决异样。能够应用 @ExceptionHandler 注解来解决 Controller 中的异样,当 Controller 中抛出异样时,会主动调用 @ExceptionHandler 注解中指定的办法来解决异样。

胜利是一个长期的过程,须要一直地致力和保持。

  • “胜利的秘诀在于保持,保持,再保持。”——张德芬
  • “胜利不是未来才有的,而是从决定去做的那一刻起,继续累积而成。”——阿斯顿·马丁
  • “只有在经验了漫长跋涉之后,能力登上现实的山巅。”——菲茨杰拉德
  • “胜利的关键在于咱们是否真正酷爱咱们所做的事件,是否做到了最好。”——贺绿汀
  • “成功者不是从不失败,而是可能从失败中振作起来。”——乔治·爱德华·伯纳德·肖
  • “不要胆怯失败,失败是通向胜利的必经之路。”——迈克尔·乔丹

胜利不是欲速不达的,它须要咱们一步一个脚印地向前走,一直地尝试和学习,一直地改良和欠缺。在这个过程中,咱们可能会遇到挫折和艰难,然而只有咱们放弃信念和勇气,坚定不移地致力,最终咱们肯定会迎来胜利的喜悦。

本文由 mdnice 多平台公布

退出移动版