c .net网站开发,十堰网络推广平台,阿里巴巴1688官网,境外电商网站建设1. Spring
1.1 核心功能
1. IOC容器
IOC#xff0c;全称为控制反转#xff08;Inversion of Control#xff09;#xff0c;是一种软件设计原则#xff0c;用于减少计算机代码之间的耦合度。控制反转的核心思想是将传统程序中对象的创建和绑定由程序代码直接控制转移到…1. Spring
1.1 核心功能
1. IOC容器
IOC全称为控制反转Inversion of Control是一种软件设计原则用于减少计算机代码之间的耦合度。控制反转的核心思想是将传统程序中对象的创建和绑定由程序代码直接控制转移到一个外部容器如框架或库来管理从而实现模块间的解耦。 将对象的控制权交给容器进行管理只需要在使用时找容器要。
如何工作
在没有控制反转的传统程序设计中程序的流程是由程序本身控制的。程序中的每个对象通常负责创建和管理它所依赖的其他对象。这导致了强耦合和难以维护的代码。
而在控制反转的情境中这种创建和查找依赖对象的工作被委托给外部系统如框架。这个外部系统负责创建对象、解决它们的依赖关系以及管理它们的生命周期。
控制反转的好处 降低耦合度通过将依赖关系的管理交给外部容器可以减少代码间的直接依赖。 提高模块的可重用性由于模块之间的耦合度降低单个模块变得更容易重用。 增强代码的可测试性控制反转使得模块间的耦合降低从而使得单元测试更加容易实现。 增强代码的可维护性代码变得更加模块化易于理解和维护。
实现方式
控制反转通常通过以下方式实现 依赖注入Dependency Injection是控制反转的一种形式其中对象的依赖项如服务、配置不是由对象本身创建而是在创建对象的时候由外部容器注入。 服务定位器Service Locator通过使用一个中心注册表对象可以在运行时从中检索依赖项。 事件驱动对象可以订阅和监听事件而不是直接调用特定的方法。
应用领域
控制反转广泛应用于现代软件开发中尤其是在使用复杂框架和库的企业级应用程序中。许多流行的框架如SpringJava、ASP.NET Core.NET等都内置了控制反转机制。
IOC容器是如何降低代码耦合性的
IOC控制反转容器通过接管对象的创建和生命周期管理从而降低代码的耦合性。在没有IOC容器的情况下对象之间的依赖关系通常是硬编码在对象内部的这导致了高度的耦合。当使用IOC容器时这种情况得到了改变 分离对象创建和使用在传统的程序设计中一个对象负责创建和管理它依赖的其他对象。这种直接的依赖关系导致代码耦合。而IOC容器接管了对象的创建过程对象只需要声明它们的依赖项而不需要知道如何创建这些依赖项。这种方式使得对象之间的耦合度大大降低。 依赖注入这是IOC的一种常见形式其中IOC容器在运行时自动“注入”对象所需的依赖项。这意味着对象不再需要自己寻找或创建它们需要的依赖项。依赖注入可以是构造函数注入、属性注入或方法注入。 配置和代码的分离在许多情况下依赖关系可以通过外部配置如XML文件、注解或特殊的配置类来定义而不是在代码中硬编码。这允许开发者在不改变代码的情况下更改依赖关系从而提高了代码的灵活性和可维护性。 更容易的单元测试由于对象不再直接创建它们的依赖项所以在单元测试时更容易替换这些依赖项比如使用Mock对象。这有助于写出更专注于单一功能的测试用例。 更好的管理和生命周期控制IOC容器通常提供了对对象生命周期的管理功能包括创建、初始化、使用和销毁等。这意味着对象的管理更加统一和集中便于跟踪和控制。
通过这些方式IOC容器减少了代码中的直接依赖关系使得代码更加模块化提高了可维护性和可扩展性。
总的来说控制反转是一种有力的设计原则用于构建松耦合、可维护和可测试的软件系统。
1.1.2 DI依赖注入
依赖注入Dependency Injection简称DI是实现控制反转Inversion of ControlIOC的一种方法。在软件工程中依赖注入指的是组件如对象或函数的依赖关系即它所需要的其他组件不是由组件本身在内部创建或查找而是由外部实体如框架、容器或另一个组件提供。这种机制使得组件之间的耦合度降低增加了代码的模块化和可测试性。
在Spring框架中依赖注入DI是核心概念之一。它允许对象定义它们的依赖即它们需要的其他对象而不是自行创建它们。Spring容器负责创建对象、解决它们的依赖关系并将所需的依赖注入到对象中。这一过程大大简化了代码的编写使得开发者可以专注于业务逻辑而不是对象的创建和管理。
Spring中的依赖注入的方式 构造函数注入通过构造函数将依赖注入到对象中。这种方法在对象创建时就提供了所有必需的依赖确保了对象的不变性。 public class MyService {private final MyRepository repository;public MyService(MyRepository repository) {this.repository repository;}
}Setter注入通过setter方法注入依赖。这种方法在对象创建后注入依赖提供了更大的灵活性。 public class MyService {private MyRepository repository;public void setRepository(MyRepository repository) {this.repository repository;}
}字段注入直接在字段上注入依赖。这是最简单的注入方式但它也降低了类的测试性和封装性。 public class MyService {Autowiredprivate MyRepository repository;
}Spring依赖注入的好处 减少耦合通过依赖注入组件之间的耦合度降低增强了模块的独立性。 增强测试性依赖注入使得在单元测试时可以轻松地用mock对象替换真实依赖。 易于维护和扩展由于依赖关系是由Spring容器管理的修改和扩展应用程序变得更容易。 声明式配置通过使用注解如Autowired或XML配置文件可以在不修改代码的情况下改变依赖关系。
注意事项 避免过度使用依赖注入虽然方便但过度使用特别是自动装配可能导致代码难以追踪和维护。 考虑使用构造函数注入相比于字段注入和setter注入构造函数注入通常被认为是更好的选择因为它可以保证依赖的不变性和完整性。 合理管理作用域在Spring中对象Bean的作用域需要合理管理以确保应用的性能和一致性。
Spring框架通过其强大的依赖注入功能极大地促进了Java企业级应用的开发使得应用程序更加模块化、易于测试和维护。
1.1.3 AOP
在Spring框架中面向切面编程Aspect-Oriented Programming简称AOP是一种编程范式它允许开发者将横切关注点cross-cutting concerns从业务逻辑中分离出来。横切关注点是那些影响多个类的问题例如日志记录、事务管理、安全性、缓存等。AOP通过提供一种分离和重用这些关注点的方式增加了代码的模块化。
AOP的核心概念 切面Aspect一个模块化的横切关注点实现。切面可以包含通知和切点。 通知Advice在切面的特定连接点上采取的动作。通知类型包括“前置通知”在方法执行之前运行、“后置通知”在方法成功完成后运行、“环绕通知”在方法运行前后都运行、“异常通知”在方法抛出异常时运行和“最终通知”无论方法如何结束都运行。 连接点Join Point程序执行的某个特定位置如类中的方法执行或异常处理。 切点Pointcut一组连接点可以通过表达式定义来匹配方法签名。切点决定了通知应该在哪些连接点执行。 引入Introduction向现有类添加新方法或属性。 目标对象Target Object被一个或多个切面通知的对象。 代理Proxy为目标对象提供横切关注点的对象。在Spring AOP中AOP代理通常是基于JDK动态代理或CGLIB代理。
AOP的使用
在Spring中AOP通常用于以下用途
日志记录自动记录方法的执行情况。事务管理声明式地管理事务使业务代码保持独立于事务代码。性能监测监测方法执行时间以便优化性能。安全控制在方法执行前进行权限检查。错误处理为方法执行过程中的错误统一处理逻辑。
实现方式
在Spring框架中AOP可以通过以下方式实现
使用AspectJ注解Spring支持使用AspectJ提供的注解如Aspect、Before、After、Around等来定义切面、通知和切点。XML配置在Spring的XML配置文件中定义切面和通知。
示例
一个简单的日志记录切面可能看起来像这样
Aspect
public class LoggingAspect {Before(execution(* com.example.service.*.*(..)))public void logBeforeMethod(JoinPoint joinPoint) {System.out.println(Before method: joinPoint.getSignature().getName());}
}这个例子中LoggingAspect 类标记为一个切面Aspect并且包含一个前置通知Before它会在指定的方法这里是com.example.service包下的所有方法执行之前运行。
通俗理解AOP
让我尝试用一个更简单的比喻来解释Spring AOP面向切面编程的原理。
想象你去餐厅吃饭你点了一些菜这就像是程序中的一次方法调用。在传统的程序设计中你的订单直接进入厨房并由厨师目标对象直接处理。
但在使用Spring AOP的情况下情景就像是在你和厨师之间增加了一个服务员代理对象。这个服务员的工作不仅仅是传递你的订单给厨师还包括了一些额外的任务比如
在将订单传递给厨师之前他可能会记录下你的订单前置通知如日志记录。如果你要求特殊处理如不要放辣他会告知厨师这些特殊要求方法拦截。当菜品做好后他可能会检查菜品质量后置通知。如果厨房出了问题比如菜品做错了他会向你报告异常通知。
在这个过程中厨师目标对象只关心如何做菜而所有额外的任务日志记录、异常处理等横切关注点都由服务员代理对象处理。这样厨师的工作就被简化了而且餐厅的管理如日志、异常处理变得更加灵活和有条理。
回到Spring AOP的世界这就意味着
目标对象厨师专注于它的主要职责业务逻辑。代理对象服务员在目标对象处理请求执行方法之前后或期间增加额外的处理步骤AOP的通知。
通过这种方式Spring AOP允许我们将某些通用功能如日志记录、安全检查从业务逻辑中抽离出来交由代理对象处理从而使业务逻辑更加清晰和易于维护。
总的来说Spring中的AOP提供了一种强大且灵活的方式来处理横切关注点使得这些逻辑从业务代码中分离从而提高了代码的可读性和可维护性。
1.1.4 事务
在Spring框架中事务管理是一个核心功能用于确保数据的一致性和完整性。Spring提供了一种声明式事务管理方式这意味着你可以通过配置和注解来管理事务而不是在代码中显式地控制事务的开始、提交和回滚。
Spring事务的核心概念 声明式事务管理通过使用注解或XML配置来管理事务这使得事务管理与业务逻辑分离降低了代码的耦合度。 事务传播行为Spring事务提供了多种事务传播行为例如REQUIRED如果当前没有事务就新建一个事务如果已经存在事务则加入这个事务、REQUIRES_NEW总是新建事务如果已经存在事务将它挂起、SUPPORTS如果存在事务则加入事务如果不存在事务则以非事务方式运行等。 事务隔离级别事务隔离级别定义了一个事务可能受其他并发事务影响的程度。Spring支持数据库提供的所有事务隔离级别如READ_COMMITTED、REPEATABLE_READ等。 事务管理器Spring支持多种类型的事务管理器最常用的是针对JDBC的DataSourceTransactionManager和针对JPA的JpaTransactionManager。
声明式事务的使用 使用Transactional注解在方法或类上添加Transactional注解可以将其标记为事务性的。你可以在该注解中指定传播行为、隔离级别、超时时间等属性。 Service
public class MyService {Transactionalpublic void myTransactionalMethod() {// 业务逻辑}
}配置事务管理器在Spring配置文件中定义事务管理器。 bean idtransactionManagerclassorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/
/bean启用事务注解在Spring配置中启用事务注解的支持。 Configuration
EnableTransactionManagement
public class AppConfig {// ...
}注意事项
确保事务方法的可见性为public。注意事务的传播行为和隔离级别以满足业务需求。在异常处理中只有来自事务方法的运行时异常RuntimeException和错误Error默认会触发回滚。如果需要对检查型异常进行回滚需要在Transactional注解中显式指定。
Spring的声明式事务管理提供了一种灵活、强大且易于维护的方式来处理事务这对于构建可靠和健壮的企业级应用至关重要。
事务的传播机制
事务的传播机制是Spring事务管理中的一个重要概念。它定义了业务方法之间交互时事务如何传播。例如当一个事务方法被另一个事务方法调用时是否应该加入到已有的事务中还是应该开启一个新的事务。Spring提供了一系列事务传播行为让开发者可以根据具体需求选择合适的策略。
以下是Spring支持的一些主要的事务传播行为 REQUIRED默认如果当前存在事务则加入该事务如果当前没有事务则创建一个新的事务。 SUPPORTS如果当前存在事务则加入该事务如果当前没有事务则以非事务方式执行。 MANDATORY如果当前存在事务则加入该事务如果当前没有事务则抛出异常。 REQUIRES_NEW创建一个新的事务如果当前存在事务则将当前事务挂起。 NOT_SUPPORTED以非事务方式执行操作如果当前存在事务则将当前事务挂起。 NEVER以非事务方式执行如果当前存在事务则抛出异常。 NESTED如果当前存在事务则在嵌套事务内执行。如果当前没有事务则其行为类似于REQUIRED。但它使用了一个单独的事务这个事务是外部事务的一个子事务如果嵌套事务失败只会回滚这个子事务。
使用场景举例 REQUIRED适用于大多数情况尤其是当你希望在一个事务中完成多个操作时。 REQUIRES_NEW适用于需要完全独立于当前事务的操作例如一个操作不应该回滚由于另一个操作引起的更改。 MANDATORY适用于必须在事务中运行的操作如果调用时没有事务环境则应该是一个错误。 SUPPORTS适用于既可以在事务中运行也可以不在事务中运行的操作不会影响事务行为。 NEVER适用于不应该在事务中运行的操作确保没有事务环境。 NESTED适用于需要独立于主事务进行单独回滚和提交的场景。
选择正确的事务传播行为对于保证事务的正确性和效率至关重要。错误的选择可能导致数据不一致或者在不必要的情况下使用事务影响性能。
导致Spring事务失效的情况有哪些
Spring事务失效可能由多种原因造成主要包括以下几个方面 事务方法不是publicSpring事务使用动态代理实现仅能拦截公共方法public。如果你在非公共方法上使用Transactional注解事务是不会被应用的。 同一个类中方法互调如果在同一个Spring Bean内部一个非事务方法调用事务方法事务是不会被应用的。因为事务是通过代理实现的而内部方法调用不会通过代理。 事务传播行为不正确如果事务方法的传播行为设置不合适例如使用PROPAGATION_NEVER或PROPAGATION_NOT_SUPPORTED可能导致事务不被启动。 数据库不支持事务如果你使用的数据库不支持事务或者配置的数据源不支持事务那么Spring事务管理自然无法正常工作。 异常处理不当默认情况下Spring仅在遇到运行时异常RuntimeException和错误Error时才回滚事务。如果你的方法抛出的是受检异常checked exception并且没有在Transactional注解中显式指定回滚事务不会回滚。 事务管理器配置错误如果事务管理器没有正确配置或者没有将事务管理器与数据源关联事务管理将无法正常工作。 使用JPA或Hibernate时清理模式配置错误在使用JPA或Hibernate时如果spring.jpa.open-in-view是false可能会导致事务在视图渲染之前就被提交。 不正确的事务隔离级别如果事务的隔离级别设置不正确可能会导致事务行为不符合预期。 多数据源问题如果应用中配置了多个数据源而没有正确指定事务管理器可能会导致事务不被应用到预期的数据库。 Transactional注解用在非Spring管理的Bean上Transactional只有在应用于Spring管理的Bean时才有效。如果注解用在Spring容器外的对象上事务是不会被管理的。
为了确保Spring事务的正确性开发者需要注意这些细节并确保Spring配置和代码使用符合事务管理的要求。
事务的实现原理
Spring事务的实现原理主要基于Spring的AOP面向切面编程和代理机制。这个机制通过事务切面和事务管理器来管理事务的生命周期包括事务的创建、提交和回滚。下面详细介绍这个过程
1. AOP和代理机制
当在Spring配置中声明了Transactional注解时Spring会通过AOP创建一个代理Proxy这个代理会环绕实际的方法。如果使用的是基于接口的代理默认情况下如果目标类实现了接口Spring使用JDK动态代理。如果目标类没有实现接口Spring使用CGLIB来创建类代理。
2. 事务切面Transaction Aspect
事务切面是Spring事务实现的核心它会拦截带有Transactional注解的方法。这个切面通过TransactionInterceptor事务拦截器来工作它会在方法执行前后执行相应的事务管理逻辑。
3. 事务管理器Transaction Manager
Spring为不同的数据访问技术提供了不同的事务管理器如DataSourceTransactionManager、HibernateTransactionManager等。事务管理器负责实际的事务管理操作如创建、提交或回滚事务。
4. 事务生命周期管理
开始事务当执行到带有Transactional注解的方法时事务管理器会根据事务属性如传播行为、隔离级别等来创建或加入一个现有事务。进行业务逻辑执行实际的业务方法。事务结束业务方法完成后根据执行过程中是否发生异常来提交或回滚事务。默认情况下只有在运行时异常unchecked exception发生时才回滚但这是可配置的。
5. 异常处理和事务回滚
如果在事务方法中抛出了异常TransactionInterceptor会捕获这些异常并根据配置决定是否回滚事务。事务的回滚规则可以通过Transactional注解的rollbackFor和noRollbackFor属性来定制。
6. 使用代理的影响
由于Spring使用代理来管理事务因此只有通过代理调用的方法才会受到事务管理的影响。这意味着类内部的非代理方法调用将无法触发事务逻辑。
总结
Spring事务的实现原理是通过AOP和代理机制在运行时拦截方法调用并根据Transactional注解和配置的事务管理器来控制事务的边界和行为。这种方式提供了一种声明式的事务管理方法使得开发者可以轻松地在业务代码中应用复杂的事务管理逻辑。
1.2 扩展功能
1.2.1 监听器
在Spring框架中监听器Listener是一种用于监听和响应应用程序事件如上下文事件、HTTP会话事件等的组件。Spring提供了事件驱动模型来处理不同类型的应用程序事件。这种模型主要包括三个主要部分事件Events、监听器Listeners和事件发布Event Publishing。
1. 事件Events
事件是应用程序的状态变化的一个封装。在Spring中所有事件都是ApplicationEvent类的子类。Spring内置了许多标准事件例如
ContextRefreshedEvent当ApplicationContext被初始化或刷新时发布。ContextStartedEvent当ApplicationContext启动时发布。ContextStoppedEvent当ApplicationContext停止时发布。ContextClosedEvent当ApplicationContext关闭时发布。RequestHandledEvent一个Web特定的事件告知一个HTTP请求已经被服务。
2. 监听器Listeners
监听器是实现了ApplicationListener接口的任何Bean用于处理特定的事件。监听器需要定义一个onApplicationEvent方法该方法会在监听到相应的事件时被调用。例如创建一个监听ContextRefreshedEvent的监听器
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;public class MyContextRefreshedListener implements ApplicationListenerContextRefreshedEvent {Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {// 执行当上下文刷新时的逻辑}
}3. 事件发布Event Publishing
事件可以通过实现ApplicationEventPublisherAware接口的Bean或者直接通过ApplicationContext发布。例如
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationEvent;public class MyEventPublisherBean implements ApplicationEventPublisherAware {private ApplicationEventPublisher publisher;Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.publisher applicationEventPublisher;}public void publishEvent(ApplicationEvent event) {publisher.publishEvent(event);}
}使用EventListener注解
从Spring 4.2开始可以使用EventListener注解来简化事件监听器的创建。这允许在不实现ApplicationListener接口的情况下直接在方法上定义监听逻辑
import org.springframework.context.event.EventListener;
import org.springframework.context.event.ContextRefreshedEvent;public class MyBean {EventListenerpublic void handleContextRefresh(ContextRefreshedEvent event) {// 处理上下文刷新事件}
}事件和监听器的应用
事件和监听器在Spring中被广泛用于
追踪应用程序的生命周期事件。在不同组件之间解耦消息的发送和接收。实现业务逻辑中的异步处理。集成第三方服务如消息队列、监控系统等。
总之Spring的事件和监听器机制提供了一种强大的方式来处理应用程序中的各种事件使得组件之间的通信更加清晰和解耦。
1.2.2 定时任务
Spring框架提供了一种简单而强大的方式来创建定时任务。这通常通过使用Scheduled注解来实现它允许你以声明式的方式定义定时任务。Spring的定时任务依赖于Spring的任务调度和执行框架。
使用Scheduled注解
在Spring中你可以通过在方法上添加Scheduled注解来创建一个定时任务。这个注解提供了几种不同的方式来指定任务的执行计划 固定延迟fixedDelay在上一个任务执行完毕后等待固定的时间。 Scheduled(fixedDelay 1000)
public void taskWithFixedDelay() {// 任务逻辑
}固定速率fixedRate按照固定的速率执行任务不考虑任务执行的时间。 Scheduled(fixedRate 1000)
public void taskWithFixedRate() {// 任务逻辑
}Cron表达式cron通过Cron表达式定义更复杂的任务调度计划。 Scheduled(cron 0 * * * * ?)
public void taskWithCronExpression() {// 任务逻辑
}启用定时任务
为了使用Scheduled注解你需要在Spring配置中启用定时任务的支持。这通常通过在配置类上添加EnableScheduling注解来实现
Configuration
EnableScheduling
public class AppConfig {// 配置类的其它部分
}注意事项 所有的定时任务默认在同一个线程池中执行意味着任务之间可能会相互影响。可以配置自定义的TaskScheduler来改变这种行为。 定时任务的执行时间受到系统时钟的影响因此应该考虑系统时间的变化比如夏令时的切换。 对于复杂的调度需求可以考虑使用像Quartz这样的更强大的调度框架。
示例
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;Component
public class MyScheduledTasks {Scheduled(fixedRate 5000)public void reportCurrentTime() {System.out.println(当前时间 System.currentTimeMillis());}
}在这个示例中reportCurrentTime方法每5秒执行一次打印当前的时间戳。
Spring的定时任务功能提供了一种简便的方法来执行定时或周期性的任务非常适合用于轻量级的后台任务调度。
1.2.3 Bean生命周期
当然让我更清晰地解释Spring Bean的生命周期。Bean的生命周期可以分为几个关键阶段这些阶段定义了Bean从创建到销毁的整个过程。这个过程涉及Spring框架如何创建、配置、初始化、使用以及销毁Bean。
1. 实例化Instantiation
创建Bean实例首先Spring容器使用构造器或工厂方法创建Bean的实例。此时Bean尚未填充属性也没有进行依赖注入。
2. 属性赋值Populate Properties
注入属性值Spring容器注入配置的属性值或引用。这通常是通过XML配置文件、Java配置或注解来完成的。
3. BeanNameAware和BeanFactoryAware
Aware接口实现如果Bean实现了BeanNameAware、BeanFactoryAware或其他以Aware结尾的接口Spring容器将相应地调用这些接口的方法。例如setBeanName方法会传递Bean的ID。
4. BeanPostProcessor前置处理
前置处理BeanPostProcessor的postProcessBeforeInitialization方法在Bean的初始化前被调用。这允许在Bean执行其初始化逻辑如PostConstruct注解的方法之前执行一些自定义逻辑。
5. 初始化Initialization
InitializingBean和PostConstruct如果Bean实现了InitializingBean接口afterPropertiesSet方法将被调用。同样带有PostConstruct注解的方法也会在此时执行。init-method如果在Bean定义中指定了init-method该指定的方法也会被调用。
6. BeanPostProcessor后置处理
后置处理BeanPostProcessor的postProcessAfterInitialization方法在Bean的初始化后被调用。
7. 使用Bean
Bean准备就绪此时Bean已完全初始化可以用于应用程序中。
8. 销毁Destruction
DisposableBean和PreDestroy当容器关闭并且Bean的作用域不是原型时如果Bean实现了DisposableBean接口destroy方法将被调用。带有PreDestroy注解的方法也会在此时执行。destroy-method如果在Bean定义中指定了destroy-method该指定的方法也会被调用。
总结
在整个生命周期中你可以通过实现特定的接口或使用注解来插入自定义的行为。BeanPostProcessor允许你在初始化阶段前后添加自定义逻辑而InitializingBean、DisposableBean和相应的注解允许你在Bean的初始化和销毁时添加自定义行为。这种灵活性是Spring框架的核心优势之一。
开始getBean-实例化-属性赋值-初始化-销毁
1.2.4 循环依赖
循环依赖是指两个或多个组件相互依赖对方形成一个闭环的依赖关系。在Spring框架中特别是在依赖注入DI中循环依赖通常指的是两个或多个Bean互相引用导致无法顺利完成创建和初始化过程。
Spring解决循环依赖的方法是三级缓存。 注意Spring只支持解决单例bean的循环依赖。 后期Spring已经默认关闭了对循环依赖的支持需要手动开启。
Spring通过三级缓存解决循环依赖的原理涉及对Bean创建过程的细致管理。在Spring中创建一个Bean通常涉及到以下几个步骤实例化、属性填充依赖注入和初始化。当两个或多个Bean互相依赖时就可能发生循环依赖。Spring通过引入三级缓存机制解决了这个问题特别是针对单例作用域的Bean。
这里是三级缓存如何工作的一个概览
1. 第一级缓存单例对象的高速缓存
用途存储完全初始化好的Bean。功能当一个Bean完全初始化后实例化、依赖注入、初始化方法调用完成它被放入这个缓存中。之后每次获取这个Bean时都是从这个缓存中直接获取。
2. 第二级缓存早期暴露对象的缓存
用途存储还未完全初始化的Bean即已经实例化但依赖注入还没有完全完成的Bean。功能这允许其他Bean引用还在创建过程中的Bean从而解决循环依赖的问题。例如如果Bean A需要注入Bean B而Bean B又依赖于Bean A当创建Bean B时可以从这个缓存中获取对Bean A的引用。
3. 第三级缓存Bean工厂的缓存
用途存储能生成Bean的工厂对象。功能当Bean实例化时会生成一个相应的工厂对象该工厂对象负责完成Bean的剩余创建过程如完成依赖注入。如果在Bean的创建过程中需要引用该Bean可以通过这个工厂对象来获取一个原始状态的Bean实例。
解决循环依赖的过程 实例化Spring首先创建Bean的实例。 提前暴露引用在Bean的属性注入之前将Bean的原始状态通过工厂对象放入第三级缓存中。 属性填充开始进行依赖注入。如果这个Bean依赖于另一个正在创建的Bean它可以通过第三级缓存中的工厂对象来获取那个Bean的引用。 初始化完成Bean的初始化如调用初始化方法。 缓存更新当Bean完全初始化后将其从第二级缓存移动到第一级缓存并从第三级缓存中移除。
注意事项
这个机制只适用于单例作用域的Bean。对于构造器注入的循环依赖Spring无法解决因为在调用构造器时Bean还没有被实例化因此无法提前暴露引用。通常建议避免循环依赖如果可能通过重构代码来消除它们。这样做可以提高代码的清晰度和可维护性。
总结起来Spring的三级缓存机制通过在Bean生命周期的不同阶段提供对Bean引用的访问从而巧妙地解决了循环依赖的问题。
2. Spring Boot
2.1 优势
依赖版本管理搭建项目更简单简化配置。通过 Java Config 替代传统 xml 配置以及引入自动配置机制内嵌 Tomcat 简化项目部署
缺点
约定优于配置虽然提高了开发效率但是可能会导致意想不到的行为
冗余依赖
对于特定需求的限制2.2 与传统 Web 项目的对比
项目结构 部署方式
2.3 常用注解
SpringBootApplication ComponentScanSpring框架的 EnableAutoConfiguration ConditionalOnXxxBean、class ConditionalOnMissingXxxBean、class
2.4 自动配置流程
Spring Boot的自动配置是其核心功能之一旨在减少显式配置的需求简化Spring应用程序的开发过程。自动配置流程主要基于条件注解和EnableAutoConfiguration注解来实现。下面是这个过程的大致步骤
1. 启动类和SpringBootApplication
当你启动一个Spring Boot应用时通常会有一个带有SpringBootApplication注解的主类。这个注解实际上是一个方便的注解它组合了Configuration、EnableAutoConfiguration和ComponentScan。
2. EnableAutoConfiguration注解
EnableAutoConfiguration是自动配置的关键。它告诉Spring Boot根据类路径下的jar依赖、定义的Bean以及各种属性设置来开始自动配置过程。
3. 寻找自动配置类
Spring Boot利用spring.factories文件来加载自动配置类。这些配置文件通常位于自动配置库比如spring-boot-autoconfigure的META-INF目录下。spring.factories文件包含了带有Configuration注解的类的列表这些类定义了如何配置Spring应用程序的各种部分。
4. 条件注解的评估
自动配置类使用条件注解如ConditionalOnClass、ConditionalOnMissingBean等来控制配置的应用。这些注解确保只有在满足特定条件时相关配置才会被应用。例如如果在类路径上有JdbcTemplate类那么与JDBC相关的自动配置就会被触发。
5. 自动配置的应用
在评估了所有条件之后满足条件的自动配置类会被应用。这些配置类可以定义Bean、设置属性等从而自动配置应用程序的不同部分。自动配置尽可能智能但也提供了适当的自定义选项。你可以通过在application.properties或application.yml文件中设置属性来覆盖自动配置的默认值。
6. 自定义和覆盖
尽管自动配置提供了合理的默认设置但你仍然可以通过定义自己的配置Bean来覆盖这些默认设置。如果你定义了某个自动配置类所期望的Bean自动配置通常会退让避免覆盖你的配置。
总结
Spring Boot的自动配置机制通过一系列的条件检查和配置类来自动配置Spring应用程序。这一过程极大地简化了配置工作使开发者可以更专注于业务逻辑。同时它也提供了足够的灵活性允许开发者在必要时覆盖或自定义特定的配置。 2.5 启动流程
Spring Boot的启动流程涉及多个关键步骤这些步骤共同工作以初始化和配置Spring应用程序。下面是Spring Boot启动时的主要过程
1. 运行主类
Spring Boot应用通常有一个包含main方法的主类这个类上标注有SpringBootApplication注解。当你运行这个主类时Spring Boot的启动流程开始。
SpringBootApplication
public class MyApp {public static void main(String[] args) {SpringApplication.run(MyApp.class, args);}
}2. 创建SpringApplication对象
当调用SpringApplication.run()时首先会创建一个SpringApplication对象。这个对象封装了应用的配置和环境。
3. 准备运行环境
SpringApplication对象准备运行环境。这包括配置Spring的profiles读取配置文件如application.properties或application.yml以及初始化日志系统等。
4. 创建应用上下文
接着Spring Boot创建一个合适的ApplicationContext实例。对于大多数web应用来说这将是一个AnnotationConfigServletWebServerApplicationContext它支持带注解的类。
5. 初始化应用上下文
一旦ApplicationContext被创建Spring Boot开始初始化它。这包括注册Bean定义、加载配置类等。
6. 应用自动配置
这是Spring Boot的核心特性。基于EnableAutoConfiguration注解Spring Boot会自动配置应用程序。这涉及到扫描spring.factories文件中列出的配置类并根据条件注解如ConditionalOnClass、ConditionalOnMissingBean应用它们。
7. 刷新应用上下文
一旦所有的Bean都被加载所有的配置都被应用ApplicationContext就会被刷新。这意味着所有的Bean实例化并调用它们的初始化方法。
8. 运行CommandLineRunner和ApplicationRunner
如果你的应用程序中有实现CommandLineRunner或ApplicationRunner接口的Bean它们的run方法将在这个时候被调用。
9. 启动内嵌的Web服务器
对于web应用Spring Boot会在这个阶段启动内嵌的web服务器如Tomcat、Jetty或Undertow。
10. 应用准备就绪
最后应用完成启动并准备接受请求。
总结
Spring Boot的启动流程涵盖了从运行主类开始到应用准备就绪的一系列复杂步骤。这个过程自动化和简化了许多传统Spring应用程序所需的显式配置和引导过程。通过这种方式Spring Boot使得创建和运行Spring应用变得更加快捷和容易。
3. Spring MVC
3.1 常用注解
Controller RestController RequestMapping GetMapping PostMapping PutMapping DeleteMapping RequestBody ResponseBody
3.2 请求处理流程
Spring MVC (Model-View-Controller) 的请求流程是 Spring 框架用于处理 web 请求的核心部分。它遵循典型的 MVC 设计模式。以下是 Spring MVC 处理请求的基本流程 接收请求用户的请求首先被前端控制器Front Controller即 DispatcherServlet 接收。DispatcherServlet 是 Spring MVC 的核心它负责接收所有的请求并将它们转发到相应的处理器。 处理器映射Handler MappingDispatcherServlet 调用 HandlerMapping 来确定每个请求的处理器Controller。基于请求的 URL、HTTP 方法等信息HandlerMapping 决定哪个 Controller 应该处理请求。 调用适当的控制器一旦确定了处理器DispatcherServlet 调用相应的 Controller。 业务逻辑处理Controller 接收请求并处理业务逻辑。它可能会与后端服务交互比如数据库或其他业务服务来处理请求并准备数据。 模型和视图的选择Controller 处理完业务逻辑后它返回一个 ModelAndView 对象该对象包含模型数据和视图名称。模型Model包含要展示的数据视图View是展示模型数据的模板。 视图解析View ResolverDispatcherServlet 使用 ViewResolver 来解析 Controller 返回的视图名称。ViewResolver 根据视图名称确定具体的视图模板。 渲染视图一旦确定了视图DispatcherServlet 将模型数据传递给视图模板。视图模板使用这些数据来生成最终的 HTML、JSON 或其他格式的响应。 返回响应生成的响应返回给 DispatcherServlet然后由它返回给用户。
这个过程涉及许多 Spring MVC 的组件例如 HandlerInterceptor拦截器、LocaleResolver本地化解析器、MultipartResolver多部分解析器等可以进一步定制请求处理流程。通过这种方式Spring MVC 提供了一个灵活、可扩展的架构来处理 Web 应用程序的请求。
3.3 扩展功能
3.3.1 统一异常处理
是Spring MVC提供的一个基于Controller实现的代理机制利用AOP实现对所有的控制器进行代理拦截所有从控制器跑出的异常进行统一处理 步骤 1. 创建一个统一异常处理类标注ControllerAdvice 或 RestControllerAdvice 注解 2. 创建对应异常类型的处理方法贴上ExceptionHandler注解并制定要处理的异常类型 3. 在方法中实现该异常的处理方案最终返回对应数据给前端
3.3.2 JSR303参数校验
JSR303 是Java规范的一项提议主要是用于服务端参数校验
通过定义一套通用的注解规范可以让服务端参数校验实现只加注解就完成对参数检验的能力。 3.3.3 参数解析器
在 Spring MVC 中参数解析器Parameter Resolvers是一种机制用于处理传入的 HTTP 请求并将它们映射到控制器方法的参数。这个过程涉及到将请求数据如路径变量、查询参数、请求体等转换为适合控制器方法参数的格式。Spring 提供了多种内置的参数解析器以及扩展点允许开发者自定义参数解析器。以下是一些常见的内置参数解析器 RequestParam 用于获取请求参数query parameters。例如RequestParam(id) String id 会将请求中的 id 参数映射到方法的 id 参数上。 PathVariable 用于处理 URI 模板变量。例如在请求路径中 /users/{userId}PathVariable(userId) 可以将 userId 的值提取出来。 RequestBody 用于处理 HTTP 请求的体部body。它通常用于处理 JSON 或 XML 数据将其反序列化为 Java 对象。需要配合相应的消息转换器如 Jackson使用。 RequestHeader 用于获取 HTTP 请求头的值。例如RequestHeader(User-Agent) String userAgent 会提取请求中的 User-Agent 头信息。 CookieValue 用于从 HTTP 请求中提取 cookie 值。 ModelAttribute 通常用于将请求参数包括 URL 参数和表单参数绑定到 Java 对象上。它也可以用于将模型属性暴露给视图。 SessionAttribute 和 RequestAttribute 用于访问存储在会话Session或请求Request中的属性。 HttpServletResponse 和 HttpServletRequest 可以直接在方法参数中使用 HttpServletRequest 或 HttpServletResponse 来访问底层的请求和响应对象。 Principal 用于访问当前认证的用户的主体信息。
除了这些内置的参数解析器Spring 还允许开发者通过实现 HandlerMethodArgumentResolver 接口来创建自定义的参数解析器。这为开发人员提供了极大的灵活性以适应各种复杂的应用场景。在自定义解析器中开发者可以定义如何解析请求数据并将其转换为控制器方法所需的参数类型。
创建一个自定义的参数解析器HandlerMethodArgumentResolver在Spring MVC中是一种高级用法允许你对如何从HTTP请求映射数据到控制器方法的参数进行精细控制。下面是创建一个自定义参数解析器的具体流程 定义解析器类 创建一个类实现 HandlerMethodArgumentResolver 接口。这个接口要求实现两个方法supportsParameter 和 resolveArgument。 实现 supportsParameter 方法 这个方法决定了你的解析器是否应该用于特定的控制器方法参数。它接收一个 MethodParameter 对象你可以检查这个参数的类型、注解等然后返回 true 或 false 来表明是否支持该参数。 实现 resolveArgument 方法 这个方法负责实际解析参数。它接收 MethodParameter、ModelAndViewContainer 和 NativeWebRequest 对象作为输入并应返回一个对象该对象将被用作控制器方法的参数值。在这个方法里你可以访问请求的内容然后基于这些信息构建和返回适当的对象。 注册解析器 一旦你的解析器类实现完成你需要将其注册到Spring MVC配置中。这通常是在一个配置类中通过扩展 WebMvcConfigurer 并重写 addArgumentResolvers 方法来完成的。在这个方法中将你的自定义解析器添加到给定的 ArgumentResolvers 列表中。 使用自定义解析器 一旦注册当Spring MVC发现控制器方法的参数被你的解析器支持时根据 supportsParameter 方法它将使用你的解析器来解析这些参数。
以下是一个简化的示例来说明这个过程
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;public class MyCustomArgumentResolver implements HandlerMethodArgumentResolver {Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.getParameterType().equals(MyCustomType.class);}Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {// 实现参数解析逻辑return new MyCustomType(/* 参数构造 */);}
}// 在Spring配置中注册解析器
Configuration
public class WebConfig implements WebMvcConfigurer {Overridepublic void addArgumentResolvers(ListHandlerMethodArgumentResolver resolvers) {resolvers.add(new MyCustomArgumentResolver());}
}在这个例子中MyCustomArgumentResolver 是一个自定义的解析器用于处理 MyCustomType 类型的参数。这个解析器被注册到Spring MVC配置中之后就可以在控制器方法中使用 MyCustomType 类型的参数了。
3.3.4 拦截器与过滤器的区别
拦截器Interceptors和过滤器Filters在Java Web应用程序中都用于处理请求和响应的预处理和后处理但它们在实现方式和使用场景上有一些关键区别
拦截器 (Interceptors) 定义与框架相关拦截器是Spring框架的一部分特别是在Spring MVC中使用。它们与Spring的上下文紧密集成。 处理范围拦截器只拦截通过Spring的DispatcherServlet的请求。这意味着它们主要用于拦截控制器Controller的动作。 灵活性与功能拦截器提供了更多的灵活性可以访问Spring的上下文、控制器和处理器方法的信息。拦截器可以在请求处理之前、之后以及渲染视图之后进行工作。 配置与实现拦截器是通过实现Spring的 HandlerInterceptor 接口或者继承 HandlerInterceptorAdapter 类来创建的并在Spring的配置文件中配置。 用途常用于处理跨切面的关注点例如日志记录、权限验证、事务处理等。
过滤器 (Filters) 定义与框架无关过滤器是Servlet规范的一部分它不依赖于Spring或任何特定的框架因此更为通用。 处理范围过滤器可以拦截几乎所有的请求包括静态资源的请求如图片、CSS和JavaScript文件。 功能过滤器主要用于在Servlet级别处理请求和响应比如修改请求头和响应头、编码请求体和响应体等。 配置与实现过滤器是通过实现 javax.servlet.Filter 接口来创建的并在web.xml文件或通过使用Java配置进行配置。 用途常用于请求的预处理比如编码处理、安全过滤、图像/数据压缩等。
总结
依赖范围拦截器依赖于Spring MVC而过滤器依赖于Servlet容器。处理层级拦截器更靠近应用程序层控制器过滤器更靠近Web服务器层。功能拦截器通常用于处理与业务逻辑相关的问题而过滤器更多用于处理通用的HTTP层面的问题。灵活性拦截器通常比过滤器提供更多的灵活性和更精细的控制因为它们可以访问Spring MVC的内部工作机制。
在实际应用中根据需求选择使用拦截器还是过滤器是非常重要的。有时它们也会一起使用以提供全面的请求处理。
4. MyBatis
4.1 特点
是一个半自动化的 ORM 框架更多是对 JDBC 的封装提供了许多动态拼接SQL的功能让程序员来关注SQL的编写。
4.2 与Hibernate的区别
MyBatis 和 Hibernate 都是在 Java 生态系统中广泛使用的持久层框架但它们在哲学、设计和使用方式上有显著的区别。以下是一些主要的区别点
1. 数据访问方式 MyBatis 是一个半自动化的ORM对象关系映射框架。它允许开发者编写SQL语句并手动映射到Java对象。主要通过XML或注解的方式配置SQL语句。提供了更多的控制权在SQL级别适合需要精细调整SQL性能和行为的场景。 Hibernate 是一个完全自动化的ORM框架隐藏了大部分的数据库交互。使用HQLHibernate Query Language或JPQLJava Persistence Query Language以及Criteria API来构建查询这些都是更接近于面向对象的方式。自动管理SQL语句的生成将数据库操作更多地映射为对象和类的操作。
2. 学习曲线和易用性 MyBatis 相对容易学习特别是对于那些已经熟悉SQL的开发者。提供了更接近数据库的操作方式对于数据库设计和SQL优化有更多的控制。 Hibernate 学习曲线较陡峭特别是对于Hibernate的缓存机制、实体生命周期、会话管理等高级特性。抽象级别更高对于不需要深入了解数据库细节的应用来说更方便。
3. 性能 MyBatis 性能通常较好因为它允许开发者编写直接的SQL语句更容易进行性能优化。提供了更精确的控制但这也意味着开发者需要花更多时间来优化SQL语句。 Hibernate 由于其自动生成SQL的特性可能会在某些复杂场景下产生不太高效的SQL。提供了强大的缓存机制可以显著提高应用性能但需要正确配置和使用。
4. 缓存机制 MyBatis 提供一级本地和二级跨会话缓存但相比于Hibernate其缓存机制较为简单。 Hibernate 提供更复杂的缓存机制包括一级缓存会话缓存和二级缓存跨会话缓存以及查询缓存。
5. 集成和兼容性 MyBatis 更容易与现有的数据库和SQL代码集成特别是在已有数据库和复杂SQL的项目中。 Hibernate 强大的JPAJava Persistence API提供者支持与JPA标准的兼容使得它在Java EE环境中集成更加自然。
总的来说选择MyBatis或Hibernate取决于项目的需求、团队的熟悉程度以及对数据库控制的需求。MyBatis适合那些需要精细控制SQL和数据库交互的场景而Hibernate适合那些需要快速开发且数据库交互不是主要瓶颈的应用。
4.3 # 与 $ 符号的区别
#取值通过预编译语句拼接SQL避免SQL注入问题支持获取简单类型String Date Long的值$取值通过直接拼接SQL语句可能产生SQL注入不支持获取简单类型String Date Long的值
4.4 缓存
4.4.1 一级缓存
默认开启作用域仅为SqlSession 级别只要当前SqlSesison关闭缓存失效 规则为SQL参数完全相同才会命中缓存该缓存的数据被缓存在内存中 由于缓存的规则其只在SqlSession级别生效一个请求-一个SqlSession 所以一级缓存没有太大用
4.4.2 二级缓存
二级缓存是Mybatis提供的一个扩展缓存的机制在一级缓存的基础上二级缓存的作用域是命名空间级别的只要这个命名空间不被销毁缓存数据不会被销毁的。
缓存规则同样是SQL参数完全相同默认是关闭的可以结合第三方库杨家实现内存或分布式缓存的实现。
执行查询时会以查询语句的SQL参数作为key查询得到的值为value 当执行了增删改操作时自动删除缓存保证数据的一致性
缺点由于缓存是命名空间级别的因此只有在该命名空间下进行的表结构操作缓存的管理才有效 员工mapper 部门mapper
4.5 分页拦截器实现原理
MyBatis的分页拦截器是基于拦截器Interceptor机制实现的这是MyBatis提供的一个强大功能允许在特定的时刻插入自定义行为例如在执行查询之前或之后。分页拦截器主要用于实现分页查询的功能而不必修改实际的查询语句。下面是分页拦截器的基本实现原理
1. 拦截器机制
MyBatis的拦截器基于Java的动态代理机制。开发者可以创建一个实现了MyBatis Interceptor 接口的类其中的 intercept 方法就是拦截器的核心。在这个方法中可以拦截执行的SQL语句和查询参数。
2. 分页拦截的流程 拦截查询操作当执行查询操作时分页拦截器会拦截这个操作。这通常发生在Executor.query()方法被调用时。 检测并修改SQL拦截器会检查当前执行的SQL是否需要分页。如果需要它会重写SQL语句加入数据库特定的分页命令如LIMIT子句在MySQL中。 参数处理同时拦截器也会处理与分页相关的参数例如当前页码和每页显示的记录数。 执行修改后的查询然后拦截器会执行修改后的SQL语句。 返回分页结果最后拦截器将查询结果封装成分页信息如总记录数、总页数、当前页的数据等并返回。
3. 示例
假设原始的SQL语句是
SELECT * FROM users;如果要对这个查询进行分页假设每页显示10条记录查询第2页那么分页拦截器会修改这个SQL为
SELECT * FROM users LIMIT 10 OFFSET 10;这个修改后的SQL语句将只返回第11到第20条记录。
4. 配置
在MyBatis配置文件中需要将这个分页拦截器注册为一个插件。
5. 优点与局限
优点分页拦截器可以让分页逻辑与业务逻辑解耦使得开发者无需在每个分页查询中手动编写分页逻辑。局限它依赖于数据库的分页语法可能需要根据不同的数据库进行调整。此外如果查询逻辑非常复杂自动化的分页改写可能不够高效或者不适用。
总的来说MyBatis的分页拦截器是一种方便且强大的工具能够有效地实现分页功能但在特定情况下可能需要针对具体的数据库和查询进行调整。
5. Spring Security
5.1 简介
Spring Security是一个功能强大且高度可定制的认证和访问控制框架是Spring生态系统中用于保护基于Spring的应用程序的标准选择。它提供了全面的安全性解决方案旨在解决企业级应用程序中的安全性问题。以下是Spring Security的一些关键特点和组件
核心特点 全面的认证和授权支持Spring Security支持多种认证机制包括表单登录、HTTP Basic、OAuth2、LDAP等并提供了强大的授权规则配置。 防范攻击它提供了防止跨站请求伪造CSRF、会话固定攻击、点击劫持等安全威胁的机制。 与Spring生态系统集成与Spring Framework紧密集成可以轻松与Spring MVC、Spring Data等其他Spring项目结合使用。 灵活的配置提供基于Java配置和XML配置的方式允许开发者根据需求定制安全策略。 扩展性通过实现自定义的认证提供者、决策管理器等组件可以扩展和定制其默认行为。
关键组件 SecurityContextHolder和SecurityContext用于存储当前安全上下文的细节包括当前用户的细节。 Authentication代表用户的认证信息如用户名和密码。 GrantedAuthority表示授权信息通常以角色的形式出现。 UserDetails提供必要的信息来构建Authentication对象。 UserDetailsService用于根据用户名检索用户的详细信息。 PasswordEncoder用于密码的加密和匹配。 FilterChainSpring Security使用一系列过滤器来提供安全性例如UsernamePasswordAuthenticationFilter用于处理表单登录。
使用流程 客户端请求用户发出请求例如登录请求。 过滤器链处理请求通过一系列Spring Security过滤器处理诸如认证、授权等安全相关的事项。 认证和授权根据配置的认证提供者进行认证并根据配置的权限规则进行授权。 成功或失败的处理根据认证和授权的结果进行相应的处理如重定向到不同的页面或返回错误信息。
使用场景
保护Web应用程序限制对URL的访问。方法级别的安全性例如使用注解保护特定的服务方法。集成OAuth2以提供单点登录SSO和资源服务器保护。实现LDAP认证、数据库认证等。
5.2 原理
Spring Security的原理基于一系列的过滤器Filters和拦截器Interceptors它们协同工作以提供认证和授权功能。这个框架遵循“默认拒绝访问”的原则即在没有明确授权的情况下用户不被允许访问任何资源。下面是Spring Security工作原理的一个概览
1. 过滤器链 (Filter Chain)
Spring Security使用Servlet过滤器来拦截请求。请求首先经过一系列Spring Security定义的过滤器这个过滤器链负责执行各种安全检查。
2. 认证 (Authentication)
认证入口点当用户尝试访问受保护的资源但未经认证时系统将用户重定向到认证入口点例如登录页面。认证过滤器如UsernamePasswordAuthenticationFilter用于处理登录表单提交的数据。认证管理器AuthenticationManager调用AuthenticationProvider后者负责与数据库或其他服务交互以验证用户凭据。
3. 授权 (Authorization)
在认证成功后请求再次通过过滤器链。安全拦截器如FilterSecurityInterceptor检查用户是否有权访问当前请求的资源。访问决策管理器AccessDecisionManager评估用户的GrantedAuthority权限与资源所需的权限。
4. 异常处理
认证异常如果认证失败如用户名/密码不正确则抛出认证异常。授权异常如果用户尝试访问无权访问的资源抛出授权异常。异常处理异常被AuthenticationEntryPoint或AccessDeniedHandler捕获并根据配置进行处理如重定向到错误页面。
5. 会话管理
Spring Security还管理用户会话包括会话固定保护、并发会话控制等。
6. 过滤器的例子
UsernamePasswordAuthenticationFilter处理表单登录。BasicAuthenticationFilter处理HTTP基本认证。CsrfFilter处理跨站请求伪造CSRF保护。LogoutFilter处理用户注销。
7. 安全上下文 (Security Context)
在整个请求处理过程中用户的认证信息存储在SecurityContextHolder中的SecurityContext中可用于在应用程序的任何位置获取当前用户信息。
总之Spring Security的原理涉及到一系列精心设计的组件和机制它们共同协作为Spring应用程序提供了全面的安全性保障。这种设计允许灵活地配置和扩展以适应不同应用程序的安全需求。
总的来说Spring Security是一个非常强大的工具它不仅提供了认证和授权的标准机制还提供了防范常见安全威胁的能力是构建安全Spring应用程序的关键组件。
6. Activiti7
Activiti7 是一个轻量级、高性能的工作流和业务流程管理 (BPM) 平台主要用于管理、执行和优化业务流程。Activiti 是一个基于 Java 的工作流引擎最初由 Alfresco Software 开发并且是 Apache 2.0 许可的开源项目。Activiti7 是 Activiti 项目的最新版本提供了一系列更新和改进。
主要特点 BPMN 2.0 支持Activiti7 完全支持业务流程模型和标记语言BPMN 2.0这是一种为工作流和业务流程图定义标准的 XML 格式。 灵活性和可扩展性Activiti7 设计灵活易于与其他应用程序和系统集成。它提供了丰富的 API使开发者能够轻松地将工作流功能集成到各种应用程序中。 轻量级和高性能Activiti7 的设计重点在于轻量级和性能使其适合于各种规模的项目从小型应用到大型企业系统。 云原生支持Activiti7 专为云环境优化支持在云环境中运行与微服务架构兼容。 Spring Boot 集成Activiti7 可以很好地与 Spring Boot 集成提供了便捷的方式来部署和管理业务流程。
应用场景
Activiti7 可用于多种业务场景包括但不限于
自动化流程自动化企业内的标准业务流程如员工请假流程、财务审批流程等。文档管理在文档审批和管理过程中执行业务逻辑。任务分配在团队或部门之间自动分配和管理任务。业务规则集成与业务规则引擎集成提供决策支持。
技术栈
Activiti7 使用 Java 作为主要开发语言但它的 REST API 允许通过网络与使用其他编程语言编写的系统交互。它通常与关系数据库一起使用以持久化流程实例、任务和其他相关数据。
总的来说Activiti7 是一个强大、灵活的工作流和 BPM 解决方案适用于需要自动化和优化其业务流程的组织和开发者。通过支持 BPMN 2.0、提供灵活的集成选项并专为云环境优化它成为了企业流程管理的流行选择。