[TOC]
Spring:古代Java开发的必备框架
Spring是一个轻量级的Java框架,它提供了各种企业级利用程序开发的工具和技术。Spring框架的外围是IoC容器和AOP框架。IoC容器使得Java应用程序的组件化变得更加容易,AOP框架使得Java应用程序的切面编程变得更加容易。Spring框架还提供了许多其余的性能,例如数据拜访、Web开发、安全性、事务管理等。
Spring创立bean的生命周期以及对应的接口和注解
Spring创立bean的生命周期蕴含以下步骤:
- 实例化Bean:Spring通过结构器或工厂办法来创立Bean实例。
- 设置Bean属性:Spring通过setter办法或间接拜访字段来设置Bean的属性值。
- BeanNameAware接口:如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()办法。
- BeanFactoryAware接口:如果Bean实现了BeanFactoryAware接口,Spring将BeanFactory实例传递给setBeanFactory()办法。
- ApplicationContextAware接口:如果Bean实现了ApplicationContextAware接口,Spring将ApplicationContext实例传递给setApplicationContext()办法。
- Pre-Initialization BeanPostProcessor:在Bean初始化之前,Spring通过调用PostProcessBeforeInitialization()办法提供了一个扩大点,能够在Bean初始化之前对Bean进行定制。
- InitializingBean接口:如果Bean实现了InitializingBean接口,Spring将调用afterPropertiesSet()办法。
- 自定义初始化办法:Bean能够自定义初始化办法,只须要在Bean定义中指定该办法的名称。
- Post-Initialization BeanPostProcessor:在Bean初始化之后,Spring通过调用PostProcessAfterInitialization()办法提供了一个扩大点,能够在Bean初始化之后对Bean进行定制。
- DisposableBean接口:如果Bean实现了DisposableBean接口,Spring将调用destroy()办法。
- 自定义销毁办法:Bean能够自定义销毁办法,只须要在Bean定义中指定该办法的名称。
在Spring中,能够应用以下注解来管制Bean的生命周期:
- @PostConstruct:指定初始化办法,相当于InitializingBean接口的afterPropertiesSet()办法。
- @PreDestroy:指定销毁办法,相当于DisposableBean接口的destroy()办法。
- @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod"):指定初始化办法和销毁办法。
Spring应用三级缓存解决循环依赖的原理
- singletonObjects:保留曾经齐全创立好的单例Bean。
- earlySingletonObjects:保留曾经实例化、然而还未填充属性的单例Bean。
- 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的具体过程如下:
- 首先,Spring会查看该Bean是否曾经创立并存储在singletonObjects缓存中。如果Bean曾经存在,则间接返回该Bean实例。这是最快的状况。
- 如果Bean不存在于singletonObjects缓存中,Spring会查看该Bean是否正在创立中。如果正在创立中,则返回一个代理对象,该代理对象会在真正的Bean创立实现后被替换成真正的Bean对象。这是为了避免循环依赖的状况。
- 如果该Bean既不存在于singletonObjects缓存中,也没有正在创立中,则Spring会创立一个ObjectFactory,该ObjectFactory负责创立该Bean实例。ObjectFactory是一个工厂办法,它负责创立和返回Bean实例。
- 而后,Spring会将该ObjectFactory存储到singletonFactories缓存中,以便下次获取该Bean实例时应用。这是为了进步创立Bean实例的效率。
- 接着,Spring会查看该Bean是否依赖于其余Bean。如果依赖于其余Bean,则会先创立依赖的Bean实例。依赖项能够是其余Bean,也能够是根本类型或汇合。
- 如果依赖的Bean实例还不存在,则Spring会递归地创立依赖的Bean实例,直到所有依赖的Bean实例都曾经创立实现。这是为了保障依赖关系正确。
- 如果所有依赖的Bean实例都曾经创立实现,则Spring会从singletonFactories缓存中获取该Bean的ObjectFactory,并应用该ObjectFactory创立该Bean实例。这是Bean实例的创立过程。
- 创立该Bean实例后,Spring会将该Bean实例存储到earlySingletonObjects缓存中,以便后续填充该Bean的属性。earlySingletonObjects缓存蕴含曾经创立的单例Bean实例,然而还没有填充属性。
- 接着,Spring会递归地填充该Bean的属性。如果该Bean的属性依赖于其余Bean,则会先创立依赖的Bean实例。填充属性之前,Spring会调用所有实现了BeanPostProcessor接口的类的postProcessBeforeInitialization()办法做一些预处理工作。这是为了提供一个扩大点,能够在Bean初始化之前对Bean进行定制。
- 如果所有依赖的Bean实例都曾经创立实现,则Spring会从singletonObjects缓存中获取依赖的Bean实例,并将依赖的Bean实例填充到该Bean的属性中。填充属性之后,Spring会再次调用所有实现了BeanPostProcessor接口的类的postProcessAfterInitialization()办法做一些后处理工作。这是为了提供一个扩大点,能够在Bean初始化之后对Bean进行定制。
- 填充该Bean的属性后,Spring会将该Bean实例存储到singletonObjects缓存中,并从earlySingletonObjects缓存中移除该Bean实例。singletonObjects缓存蕴含曾经创立的单例Bean实例,并曾经填充了属性。
- 最初,Spring会递归地解决该Bean的后置处理器,而后返回该Bean实例。如果Bean实现了InitializingBean接口,Spring会调用其afterPropertiesSet()办法,这是Bean初始化之后的最初一步。如果Bean实现了DisposableBean接口,Spring会在Bean销毁之前调用其destroy()办法。
Spring应用AOP
根本过程如下:
- 在配置类上增加@EnableAspectJAutoProxy注解,启用AspectJ主动代理。
- 创立一个切面类,并且在该类上应用@Aspect注解来标识该类为切面类。
- 在切面类中定义一个或多个切点,用来匹配须要拦挡的办法。
- 在切面类中定义一个或多个告诉,用来在办法执行前、执行后或抛出异样时执行一些额定的逻辑。
- 将切面类增加到Spring的容器中。
以下是一个应用注解形式实现AOP的示例:
@Aspect@Componentpublic 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()); }}@Servicepublic 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的事务管理能够通过如下形式来应用:
- 配置事务管理器:Spring提供了多种事务管理器,如DataSourceTransactionManager、HibernateTransactionManager等。能够通过配置事务管理器来抉择适宜的事务管理器。
- 配置事务属性:能够通过配置事务属性来指定事务的流传行为、隔离级别、超时工夫、只读等个性。
- 应用@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的实现次要包含以下内容:
实现了PlatformTransactionManager接口,用于治理事务的生命周期。PlatformTransactionManager接口是Spring事务管理器的外围接口,它定义了事务的生命周期和状态转换规则。DataSourceTransactionManager实现了PlatformTransactionManager接口,用于治理基于DataSource的事务。PlatformTransactionManager接口包含以下办法:
- getTransaction(TransactionDefinition definition):获取一个新的事务或将以后线程中的事务退出到以后办法的事务中。
- commit(TransactionStatus status):提交以后事务。
- rollback(TransactionStatus status):回滚以后事务。
- 实现了TransactionDefinition接口,用于定义事务的流传行为、隔离级别、超时工夫、只读等个性。TransactionDefinition接口定义了事务的属性,包含流传行为、隔离级别、超时工夫、只读等。DataSourceTransactionManager实现了TransactionDefinition接口,用于指定基于DataSource的事务的属性。
- 实现了TransactionStatus接口,用于跟踪事务的状态。TransactionStatus接口定义了事务的状态,包含未提交、已提交和已回滚。DataSourceTransactionManager实现了TransactionStatus接口,用于跟踪基于DataSource的事务的状态。
- 实现了TransactionSynchronizationManager类,用于治理事务的同步状态。TransactionSynchronizationManager类用于治理事务的同步状态,包含事务的开始、完结和回滚等操作。DataSourceTransactionManager应用TransactionSynchronizationManager类来治理基于DataSource的事务的同步状态。
- 实现了TransactionAspectSupport类,用于反对基于AspectJ的事务告诉。TransactionAspectSupport类是Spring事务管理的外围类,它实现了基于AspectJ的事务告诉逻辑。DataSourceTransactionManager应用TransactionAspectSupport类来反对基于AspectJ的事务告诉。
DataSourceTransactionManager的工作流程
- 当一个办法被标记为@Transactional时,Spring会创立一个代理对象来代理该办法。
- 代理对象会调用TransactionAspectSupport类的invokeWithinTransaction()办法,该办法会在事务的上下文中执行指标办法。
- 在invokeWithinTransaction()办法中,会调用DataSourceTransactionManager的doBegin()办法来开启事务。
- 在doBegin()办法中,会获取以后线程中的Connection对象,并将其设置为事务的连贯。
- 如果以后线程中没有Connection对象,则会从DataSource中获取一个新的Connection对象,并将其设置为事务的连贯。
- 如果事务的隔离级别不是默认值,则会将事务的隔离级别设置到Connection对象上。
- 如果事务的超时工夫不是默认值,则会将事务的超时工夫设置到Connection对象上。
- 在指标办法执行结束后,会调用TransactionAspectSupport类的invokeWithinTransaction()办法的afterCompletion()办法来提交或回滚事务。
- 在afterCompletion()办法中,会调用DataSourceTransactionManager的doCleanupAfterCompletion()办法来清理事务状态。
- 在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多平台公布