# spring-learn **Repository Path**: hrbu2024/spring-learn ## Basic Information - **Project Name**: spring-learn - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-11-02 - **Last Updated**: 2026-11-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 框架的迭代 Spring SpringMVC MyBaits ( SSM ) SSH: Struts1.x(MVC) Spring(解耦) Hibernate( 持久层 JBDC封装) SSH: Struts2.x(MVC) Spring(解耦) Hibernate( 持久层 JBDC封装) SSI: Struts2.x (MVC) Spring (解耦) IBatis (1.x 2.x)( 持久层 JBDC封装) SSI: SpringMVC(MVC) Spring (解耦) IBatis (1.x 2.x)( 持久层 JBDC封装) SSM: SpringMVC(MVC) Spring (解耦) MBatis (3.X)( 持久层 JBDC封装) # Spring 介绍 [Spring | Home](https://spring.io/) [Spring Framework Documentation :: Spring Framework](https://docs.spring.io/spring-framework/reference/6.2/index.html) Spring是一个基于java的轻量级的、一站式框架。 虽然Spring是一个轻量级框架,但并不表示它的功能少。实际上,spring是一个庞然大物,包罗万象。 时至今日,Spring已经成为java世界中事实上的标准。 Spring之父:Rod Johnson(罗德.约翰逊) 他是悉尼大学音乐学博士,而计算机仅仅是学士学位。 由于Rod对JAVAEE笨重、臃肿的现状深恶痛绝,以至于他将他在JAVAEE实战中的经历称为噩梦般的经历。他决定改变这种现状,于是就有了Spring。 ![image-20261102084608773](assets/image-20261102084608773.png) ![img](assets/1604979623542-f6978c97-76d9-4158-8051-ce4f898bbcc4.png) Spring 总共大约有 20 个模块,由 1300 多个不同的文件构成。而这些组件被分别整合在6 个模块中: 1. 核心容器(Core Container) 2. AOP(Aspect Oriented Programming) 3. 设备支持(Instrmentation) 4. 数据访问及集成(Data Access/Integeration) 5. Web报文发送(Messaging) 6. Test测试 ## 两大核心 - IOC/DI - IOC:控制反转(Inversion of Control):它是一种控制权的转移。即组件与组件之间的依赖由主动变为被动。也就是说:应用程序本身不再负责组件的创建、维护等,而是将控制权移交出去。从这一点来说,几乎所有的框架都是IOC框架。 - ​ DI:依赖注入(Dependency Injection):依赖其他容器(比如spring)来创建和维护所需要的组件,并将其注入到应用程序中。 - IOC 控制翻转, Service 依赖Dao,原来需要在serice 中new Dao,使用IOC容器 - DI 将dao 放到Service 过程 依赖注入 - AOP: 面相切面变成 # 上手Helloworld 聚合项目 - spring-learn - 01-spring-helloword-xml - 02-spring-helloword-xml - 03-spring-helloword-xml - 04-spring-helloword-xml - 05-spring-helloword-xml - 06-spring-helloword-xml - 依赖 - 父项目定义版本 - 子项目使用依赖(无需再重复编写版本号) ## 创建项目 ![image-20261102085815374](assets/image-20261102085815374.png) ![image-20261102085915252](assets/image-20261102085915252.png) ## 编写依赖 父项目pom.xml ```xml 4.0.0 com.neuedu.spring spring-learn 1.0 pom spring-learn http://maven.apache.org 01-spring-helloword-xml UTF-8 6.2.19 org.springframework spring-core ${spring.version} compile org.springframework spring-beans ${spring.version} compile org.springframework spring-context ${spring.version} compile org.springframework spring-expression ${spring.version} compile ``` 子项目 pom.xml ```xml 4.0.0 com.neuedu.spring spring-learn 1.0 01-spring-helloword-xml jar 01-spring-helloword-xml http://maven.apache.org UTF-8 org.springframework spring-core org.springframework spring-beans org.springframework spring-context org.springframework spring-expression ``` ## 使用Qualifier注解区分多个同名的类型 ![image-20261102142945966](assets/image-20261102142945966.png) # 使用配置类代替配置文件(spring-beans.xml) 04-spring-javaconfig ```java package com.neuedu.spring; import org.springframework.context.annotation.ComponentScan; /*** * * 项目名称: spring-learn * 类名称:com.neuedu.spring * 类描述: 使用Java类代替配置文件 * 创建人:金山老师 * 创建时间:2026/11/02 14:49 * 版本:1.0 * */ // @ComponentScan("com.neuedu.spring") public class SpringApp { } ``` ![image-20261102145523237](assets/image-20261102145523237.png) junit的报错 可以不用管 ![image-20261102145452432](assets/image-20261102145452432.png) D:\app\Java\jdk-21\bin\java.exe -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\app\JetBrains\IntelliJ IDEA 2024.3.1.1\lib\idea_rt.jar=54401:D:\app\JetBrains\IntelliJ IDEA 2024.3.1.1\bin" -javaagent:C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2024.3\captureAgent\debugger-agent.jar -Dkotlinx.coroutines.debug.enable.creation.stack.trace=false -Ddebugger.agent.enable.coroutines=true -Dkotlinx.coroutines.debug.enable.flows.stack.trace=true -Dkotlinx.coroutines.debug.enable.mutable.state.flows.stack.trace=true -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath "C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-launcher\1.14.4\junit-platform-launcher-1.14.4.jar;C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-engine\1.14.4\junit-platform-engine-1.14.4.jar;C:\Users\Administrator\.m2\repository\org\opentest4j\opentest4j\1.3.0\opentest4j-1.3.0.jar;C:\Users\Administrator\.m2\repository\org\junit\platform\junit-platform-commons\1.14.4\junit-platform-commons-1.14.4.jar;C:\Users\Administrator\.m2\repository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar;C:\Users\Administrator\.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.14.4\junit-jupiter-engine-5.14.4.jar;C:\Users\Administrator\.m2\repository\org\junit\jupiter\junit-jupiter-api\5.14.4\junit-jupiter-api-5.14.4.jar;D:\app\JetBrains\IntelliJ IDEA 2024.3.1.1\lib\idea_rt.jar;D:\app\JetBrains\IntelliJ IDEA 2024.3.1.1\plugins\junit\lib\junit5-rt.jar;D:\app\JetBrains\IntelliJ IDEA 2024.3.1.1\plugins\junit\lib\junit-rt.jar;D:\workspace\spring-learn\04-spring-javaconfig\target\test-classes;D:\workspace\spring-learn\04-spring-javaconfig\target\classes;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-context\6.2.19\spring-context-6.2.19.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-aop\6.2.19\spring-aop-6.2.19.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-beans\6.2.19\spring-beans-6.2.19.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-core\6.2.19\spring-core-6.2.19.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-jcl\6.2.19\spring-jcl-6.2.19.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-expression\6.2.19\spring-expression-6.2.19.jar;D:\app\apache-maven-3.9.9\jarrepository\io\micrometer\micrometer-observation\1.15.12\micrometer-observation-1.15.12.jar;D:\app\apache-maven-3.9.9\jarrepository\io\micrometer\micrometer-commons\1.15.12\micrometer-commons-1.15.12.jar;D:\app\apache-maven-3.9.9\jarrepository\org\springframework\spring-test\6.2.19\spring-test-6.2.19.jar;D:\app\apache-maven-3.9.9\jarrepository\org\junit\jupiter\junit-jupiter-api\5.14.4\junit-jupiter-api-5.14.4.jar;D:\app\apache-maven-3.9.9\jarrepository\org\opentest4j\opentest4j\1.3.0\opentest4j-1.3.0.jar;D:\app\apache-maven-3.9.9\jarrepository\org\junit\platform\junit-platform-commons\1.14.4\junit-platform-commons-1.14.4.jar;D:\app\apache-maven-3.9.9\jarrepository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 com.neuedu.spring.service.UserServiceTest,queryUser org.junit.platform.launcher.core.DiscoveryIssueException: TestEngine with ID 'junit-jupiter' encountered a critical issue during test discovery: (1) [ERROR] MethodSelector [className = 'com.neuedu.spring.service.UserServiceTest', methodName = 'queryUser', parameterTypes = '', classLoader = null] resolution failed Source: MethodSource [className = 'com.neuedu.spring.service.UserServiceTest', methodName = 'queryUser', methodParameterTypes = ''] at com.neuedu.spring.service.UserServiceTest.queryUser(SourceFile:0) Cause: java.lang.ClassCircularityError: java/lang/WeakPairMap$Pair$Weak at java.base/java.lang.WeakPairMap$Pair.weak(WeakPairMap.java:201) at java.base/java.lang.WeakPairMap.putIfAbsent(WeakPairMap.java:123) at java.base/java.lang.Module.implAddReads(Module.java:551) at java.base/java.lang.Module.implAddReads(Module.java:512) at java.base/java.lang.System$2.addReads(System.java:2422) at java.base/jdk.internal.module.Modules.addReads(Modules.java:90) at java.base/java.lang.reflect.Proxy$ProxyBuilder.lambda$getDynamicModule$1(Proxy.java:915) at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329) at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205) at java.base/java.lang.reflect.Proxy$ProxyBuilder.getDynamicModule(Proxy.java:905) at java.base/java.lang.reflect.Proxy$ProxyBuilder.proxyClassContext(Proxy.java:840) at java.base/java.lang.reflect.Proxy$ProxyBuilder.(Proxy.java:638) at java.base/java.lang.reflect.Proxy$ProxyBuilder.(Proxy.java:643) at java.base/java.lang.reflect.Proxy.lambda$getProxyConstructor$0(Proxy.java:429) at java.base/jdk.internal.loader.AbstractClassLoaderValue$Memoizer.get(AbstractClassLoaderValue.java:329) at java.base/jdk.internal.loader.AbstractClassLoaderValue.computeIfAbsent(AbstractClassLoaderValue.java:205) at java.base/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:427) at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1034) at java.base/sun.reflect.annotation.AnnotationParser$1.run(AnnotationParser.java:301) at java.base/sun.reflect.annotation.AnnotationParser$1.run(AnnotationParser.java:299) at java.base/java.security.AccessController.doPrivileged(AccessController.java:319) at java.base/sun.reflect.annotation.AnnotationParser.annotationForMap(AnnotationParser.java:299) at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:288) at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:121) at java.base/sun.reflect.annotation.AnnotationParser.parseSelectAnnotations(AnnotationParser.java:102) at java.base/sun.reflect.annotation.AnnotationType.(AnnotationType.java:146) at java.base/sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:85) at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:262) at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:121) at java.base/sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:73) at java.base/java.lang.Class.createAnnotationData(Class.java:4246) at java.base/java.lang.Class.annotationData(Class.java:4235) at java.base/java.lang.Class.getAnnotation(Class.java:4118) at java.base/java.lang.reflect.AnnotatedElement.isAnnotationPresent(AnnotatedElement.java:292) at java.base/java.lang.Class.isAnnotationPresent(Class.java:4128) at org.junit.platform.commons.util.AnnotationUtils.findAnnotation(AnnotationUtils.java:136) at org.junit.platform.commons.util.AnnotationUtils.isAnnotated(AnnotationUtils.java:105) at org.junit.platform.commons.support.AnnotationSupport.isAnnotated(AnnotationSupport.java:97) at org.junit.jupiter.engine.discovery.predicates.TestClassPredicates.isAnnotatedButNotComposed(TestClassPredicates.java:168) at org.junit.jupiter.engine.discovery.predicates.TestClassPredicates.lambda$new$0(TestClassPredicates.java:47) at org.junit.jupiter.engine.discovery.predicates.TestClassPredicates.lambda$new$3(TestClassPredicates.java:54) at org.junit.jupiter.engine.discovery.MethodSelectorResolver.resolve(MethodSelectorResolver.java:105) at org.junit.jupiter.engine.discovery.MethodSelectorResolver.resolve(MethodSelectorResolver.java:78) at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.lambda$resolve$2(EngineDiscoveryRequestResolution.java:150) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1685) at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129) at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647) at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:189) at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:126) at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveCompletely(EngineDiscoveryRequestResolution.java:92) at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.run(EngineDiscoveryRequestResolution.java:83) at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver.resolve(EngineDiscoveryRequestResolver.java:149) at org.junit.jupiter.engine.discovery.DiscoverySelectorResolver.resolveSelectors(DiscoverySelectorResolver.java:63) at org.junit.jupiter.engine.JupiterTestEngine.discover(JupiterTestEngine.java:70) at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:195) at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverSafely(EngineDiscoveryOrchestrator.java:174) at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:119) at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:84) at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:104) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:91) at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) at org.junit.platform.launcher.core.InterceptingLauncher.lambda$execute$1(InterceptingLauncher.java:39) at org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor.intercept(ClasspathAlignmentCheckingLauncherInterceptor.java:25) at org.junit.platform.launcher.core.InterceptingLauncher.execute(InterceptingLauncher.java:38) at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:66) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55) Process finished with exit code -1 # 使用包扫描的形式注册 ![image-20261103083917987](assets/image-20261103083917987.png) ![image-20261103083946742](assets/image-20261103083946742.png) - Controller ( 目前可以随便写 后面使用Spirngmvc的时候有特殊要求) - @RestController - Repository - Service - Component 除了@Component这个泛指组件的注解外,Spring还提供了与@Component功能相同的三个语义化注解。 1. @Service 业务层组件 2. @Controller 控制层组件 3. @Repository 数据层组件 修改上面代码,使用@Repository 和 @Service 替换 dao 与 service 组件上的注解。 # BeanFactory与ApplicationContext 获取Spring容器也可以使用BeanFactory接口。BeanFactory与ApplicationContext的区别是: 1. BeanFactory Bean工厂(org.springframework.beans.factory.BeanFactory)是Spring框架最核心的接口,提供了IoC的配置机制,使管理不同类型的Java对象成为可能。特点是:采用延迟加载Bean,直到第一次使用Bean实例时才会创建Bean。 2. ApplicationContext 应用上下文(org.springframework.context.ApplicationContext),继承自BeanFactory,提供了更多面向应用的功能,比如国际化支持、框架事件体系,更易于创建实际应用。 应用时,我们一般称BeanFactory为IoC容器,ApplicationContext为应用上下文: 1. BeanFactory是Spring框架的基础设施,面向Spring本身; 2. ApplicationContext面向使用Spring框架的开发者; 3. 几乎所有的应用场合都可以直接使用ApplicationContext而非底层的BeanFactory; ![image-20261102160353886](assets/image-20261102160353886.png) # AOP 面向切面编程 AOP:全称是 Aspect Oriented Programming 即:面向切面编程。 简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强。 即当需要扩展功能时,传统方式采用纵向继承方式实现。但这种方式有很多缺点。 比如:父类方法名称改变时,子类也要修改。给多个方法扩展功能时,子类也需要修改。 因此,spring的AOP,实际上是采用横向抽取机制,取代传统的纵向继承体系。 实现AOP示意图: 1. 先将方面代码抽取出来 ![img](assets/1604979623887-9e3b1c96-0dcf-46e2-ad14-238af06d56dd.png) 2. 运行时将业务代码和方面代码编织在一起 ![img](assets/1604979623883-6aaf0e7d-d06c-45ca-928c-3d9cdb5aca49.png) ![image-20261102163712850](assets/image-20261102163712850.png) ![image-20261102163725449](assets/image-20261102163725449.png) ​ 通知 Around ### 切面(Aspect) 切面是切点和通知组成,通知和切点共同定义了切面的全部内容即:它是什么,在何时何处完成其功能; 举例:将pointcut和Advice配置整合的过程切面 ### 连接点(Joinpoint) 连接点是在应用执行过程中能够插入切面的一个点,Spring仅支持方法的连接点,即仅能在方法调用前,方法调用后,方法抛出异常时及方法调用前后插入切面代码。 . 举例:如果在insert之前执行扩展(增强、通知),简单理解insert这个方法可以称之为连接点。 连接点: 1 Com.neuedu.service.StuServiceImpl.insert() 连接点: 2 Com.neuedu.service.UserServiceImpl.insert() ### 切点(Pointcut) ``` Com.neuedu.service.*Impl.insert() ``` ### 通知(Advice)、增强 切面的工作被成为通知,定义了切面是什么及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题,它应该在某个方法被调用之前?之后?等。 举例:额外定义一个方法想要在连接点上进行扩展的功能 #### Spring切面可以应用5种类型的通知: 前置通知(Before)在目标方法被调用之前调用通知功能; 后置通知(After)在目标方法被完成之后调用通知功能,不关心方法的输出是什么; 环绕通知(Around advice)通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为; 异常通知(After-throwing)在目标方法抛出异常后调用通知; 返回通知(After-returning)在目标方法成功执行之后调用通知; ### 目标对象(Target) 通知逻辑的织入目标类。如果没有AOP,那么目标业务类需要自己实现所有的逻辑,在AOP的帮助下,目标类只需要实现那些非横切逻辑的程序逻辑,而比如事务管理等这些横切逻辑就可以使用AOP动态织入特定的连接点上。 举例:两个Service即是目标对象 ### 引入(Introduction) 引介是一种特殊的通知,为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过AOP的引介功能,也可以动态地为该业务类添加接口的实现逻辑,使业务类成为这个接口的实现类。 几乎由框架完成,我们可以暂时透明 ### 代理(Proxy) 一个类被AOP织入通知后,就产生一个结果类,它是融合了原类和通知逻辑的代理类。根据不同的代理方式,代理类既可能是和原类具有相同接口的类,也可能就是原类的子类,所以可以采用与调用原类相同的方式调用代理类。 举例:IOC容器创建的两个Service类型对象 ### 织入(Weaving) 织入是将通知添加到目标类的具体连接点上的过程.AOP就像一台织布机,将目标类,通知或引介编织到一起。 AOP有三种织入方式: ①编译期织入:切面在目标类编译时被织入,需要特殊的编译器; ②类装载期织入:切面在目标类加载到JVM时被织入,需要特殊的类装载器; ③动态代理织入:切面在应用运行的某个时刻呗织入,AOP容器会为目标对象动态创建一个代理对象; - 编写Service - 增强的代码(通知) - 配置前面 05-aop-xml ![image-20261102163937295](assets/image-20261102163937295.png) ![image-20261102165237243](assets/image-20261102165237243.png) # Spring整合Mybatis - Spring的项目(xml、javaconfig) - 添加依赖 - spring-context - spring-aop - aspectjweaver - spring-test - junit - spring-jdbc - mysql驱动 - mybatis - mybatis-spring - 数据源:druid - lombok - 编写service - 编写配置文件 spring-mybatis.xml - 包扫描 - 编写MyBatis - 核心配置文件 SqlMapConfig.xml - 编写实体类 Emp - 编写EmpMapper.xml - 编写EmpMapper.java - 就的SqlSessionFactory测试 - 整合 - 数据源 druid - 把SqlSessionFactory放到IOC容器中 - 在容器中管理Mapper的代理对象 - 整合测试 使用@Autowired从容器中获取Mapper ## 创建项目 ![image-20261103114719625](assets/image-20261103114719625.png) ## 添加依赖 ### 父项目 ```xml 4.0.0 com.neuedu.spring spring-learn 1.0 pom spring-learn http://maven.apache.org 01-spring-helloword-xml 02-spring-package-scan 03-spring-qualifier 04-spring-javaconfig 05-aop-xml 06-aop-xml-annotation 07-aop-javaconfig-annotation 08-spring-mybatis-xml UTF-8 6.2.19 5.14.4 1.8.7 8.4.0 3.5.6 1.18.48 1.2.28 4.0.0 org.springframework spring-core ${spring.version} compile org.springframework spring-aop ${spring.version} compile org.aspectj aspectjweaver ${aspectj.version} org.springframework spring-beans ${spring.version} compile org.springframework spring-context ${spring.version} compile org.springframework spring-expression ${spring.version} compile org.springframework spring-test ${spring.version} compile org.springframework spring-jdbc ${spring.version} compile org.junit.jupiter junit-jupiter-api ${junit.version} test com.mysql mysql-connector-j ${mysql.version} compile org.mybatis mybatis ${mybatis.version} org.projectlombok lombok ${lombok.version} provided com.alibaba druid ${druid.version} compile org.mybatis mybatis-spring ${mybatis.spring.version} compile ``` ### 子项目 ```xml 4.0.0 com.neuedu.spring spring-learn 1.0 08-spring-mybatis-xml jar 08-spring-mybatis-xml http://maven.apache.org UTF-8 org.springframework spring-context org.springframework spring-aop org.aspectj aspectjweaver org.springframework spring-test org.springframework spring-jdbc org.junit.jupiter junit-jupiter-api com.mysql mysql-connector-j org.mybatis mybatis org.projectlombok lombok com.alibaba druid org.mybatis mybatis-spring ``` ![image-20261103133249356](assets/image-20261103133249356.png) ## 搭建spring ### 编写Service ```java package com.neuedu.spring.service; import com.neuedu.spring.po.Emp; import org.springframework.stereotype.Service; /*** * * 项目名称: spring-learn * 类名称:com.neuedu.spring.service * 类描述: * 创建人:金山老师 * 创建时间:2026/11/03 13:36 * 版本:1.0 * */ @Service public class EmpService { public Emp queryById(int id){ System.out.println("根据id查询数据库"); return new Emp(); //根据id查询数据库 } } ``` ### 配置文件 spring-mybaits.xml ```xml ``` ### 单元测试 ```java package com.neuedu.spring.service; import com.neuedu.spring.po.Emp; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.junit.jupiter.api.Assertions.*; /*** * * 项目名称: spring-learn * 类名称:com.neuedu.spring.service * 类描述: * 创建人:金山老师 * 创建时间:2026/11/03 13:39 * 版本:1.0 * */ @SpringJUnitConfig(locations = "classpath:spring-mybaits.xml") class EmpServiceTest { @Autowired private EmpService empService; @Test void queryById1() { System.out.println(empService); Emp emp = empService.queryById(10); } } ``` ## 在spring中管理数据源 获取连接对象Connection Druid [Apache Druid | Apache® Druid](https://druid.apache.org/) ![image-20261103140409522](assets/image-20261103140409522.png) ### 单元测试 ```java package com.neuedu.spring.service; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; /*** * * 项目名称: spring-learn * 类名称:com.neuedu.spring.service * 类描述: * 创建人:金山老师 * 创建时间:2026/11/03 14:01 * 版本:1.0 * * * * spring-mybatis.xml * spring-mybatis.xml * * */ @SpringJUnitConfig(locations = "classpath:spring-mybatis.xml") public class DataSourceTest { @Autowired private DataSource dataSource; @Test public void testConnection(){ try { Connection connection = dataSource.getConnection(); System.out.println("connection = " + connection); } catch (SQLException e) { throw new RuntimeException(e); } } } ``` ## 整合MyBaits ### 编写SqlMapconfig.xml ```xml ``` ### 实体类 ```java package com.neuedu.spring.po; import lombok.Data; import java.util.Date; /*** * * 项目名称: spring-learn * 类名称:com.neuedu.spring.po * 类描述: * 创建人:金山老师 * 创建时间:2026/11/03 13:37 * 版本:1.0 * */ @Data public class Emp { private Integer empno ; private String ename ; private String job ; private Integer mgr ; private Date hiredate ; private Double sal ; private String comm ; private Double deptno ; } ``` ### Mapper.java ![image-20261103144801181](assets/image-20261103144801181.png) ```java package com.neuedu.spring.mapper; import com.neuedu.spring.po.Emp; import java.util.List; /*** * * 项目名称: mybatis-app * 类名称:com.neuedu.mybatis.mapper * 类描述: * 创建人:金山老师 * 创建时间:2026/10/26 10:40 * 版本:1.0 * */ public interface EmpMapper { public List selectList(); public Emp selectById( int id ); public long total( ); public int updateById(Emp emp); public int insert(Emp emp); public int deleteById (int id ); } ``` ### Mapper.xml ```xml `empno`, `ename`, `job`, `mgr`, `hiredate`, `sal`, `comm`, `deptno` UPDATE `emp` `ename` = #{ename}, `job` = #{job}, `mgr` = #{mgr}, `hiredate` = #{hiredate}, `sal` = #{sal}, `comm` = #{comm}, `deptno` = #{deptno}, WHERE `empno` = #{empno} ; INSERT INTO `emp` `empno` , `ename` , `job` , `mgr` , `hiredate` , `sal` , `comm` , `deptno` , VALUES #{empno}, #{ename}, #{job}, #{mgr}, #{hiredate}, #{sal}, #{comm}, #{deptno}, delete from emp where empno = #{empno} ``` ## 使用spring管理 SqlSessionFactory 在spring-mybaits.xml中配置 ```xml ``` ## 在容器中声明一个Mapper ![image-20261103144724500](assets/image-20261103144724500.png) ## 批量注册Mapper到Spring容器 ```xml ``` ![image-20261103150346080](assets/image-20261103150346080.png) # 事务管理器 使用AOP 在 需要添加事务的 service方法上 增加额外的代码( 通知、增强 ) 只需要配置事务管理器 ``` ``` 在serice 中编写了一个需要事务的方法 ```java /** * sal 字段暂时当做 账户余额 * @param success * @return */ public boolean transfer(boolean success){ int id1 = 7369; //SMITH 7369 800.00 + 500 = 1300 int id2 = 7788; //SCOTT 7788 3000.00 - 500 = 2500 Emp smith = empMapper.selectById(id1); Emp scott = empMapper.selectById(id2); //内存中修改了下数据 smith.setSal(smith.getSal() + 500); scott.setSal(smith.getSal() - 500); int count1 = empMapper.updateById(smith); //中间过程还有一些代码逻辑,可能产生错误 if(!success){ throw new RuntimeException("保存smith的余额之后报错了 "); } int count2 = empMapper.updateById(scott); return count1 + count2 == 2; } ``` ## 单元测试 ```java @Test void transfer() { //success 模拟代码是否成功、出错 boolean success = false; boolean result = empService.transfer(success); System.out.println("result = " + result); } ``` ## 添加事务 在容器中声明事务管理器 ```xml ``` ## 传播特性 ![image-20261104113820438](assets/image-20261104113820438.png) ## 使用@Transactional待提xml切面 ![image-20261104133253867](assets/image-20261104133253867.png) # 纯注解的方式实现spring-mybais整合 ![image-20261104133409008](assets/image-20261104133409008.png) # SpringMVC [SpringMVC 官网文档](https://docs.spring.io/spring-framework/reference/6.2/web.html) ![image-20261104162214713](assets/image-20261104162214713.png) ![img](assets/1604979789045-b6ac3995-e979-4b22-a2e6-41e1b4ae1383.png) - web项目 - 配置tomcat - 添加依赖 - Handler(Controller)自定义 - 编写-spring-web.xml 容器的配置文件 - web.xml - 配置前端控制器(DispatcherServlet) - 读取spring-web.xml - 发布到Tomcat测试 ## HelloWorld ![image-20261104141236121](assets/image-20261104141236121.png) ### 添加依赖 需要父项目和子项目中都添加依赖 ```xml 4.0.0 com.neuedu.spring spring-learn 1.0 12-springmvc-helloworld war 12-springmvc-helloworld Maven Webapp jakarta.servlet jakarta.servlet-api org.springframework spring-webmvc ``` ![image-20261104141437701](assets/image-20261104141437701.png) ![image-20261104141503858](assets/image-20261104141503858.png) ### 编写Controller ```java package com.neuedu.his.controller; import jakarta.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import java.sql.Array; import java.util.ArrayList; import java.util.List; /*** * * 项目名称: spring-learn * 类名称:com.neuedu.his.controller * 类描述: * 创建人:金山老师 * 创建时间:2026/11/04 14:22 * 版本:1.0 * */ @Controller public class UserController { /*** * http://localhost:8080/web/user/index * @param request * @return */ @RequestMapping("/user/index") public String index(HttpServletRequest request){ //从数据库查询数据 List list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add("张三"+i); } //设置数据 request.setAttribute("userList",list); return "/user/list.jsp"; } } ``` ```jsp <%@ page import="java.util.List" %><%-- Created by IntelliJ IDEA. User: Administrator Date: 2026/11/4 Time: 14:23 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Title

用户表格

<% List list = (List) request.getAttribute("userList"); %> <% for (int i = 0; i < list.size(); i++) { String name = list.get(i); %> <% } %>
序号 姓名
<%=i%> <%=name%>
``` 配置核心的配置文件 ### spring-mvc.xml ```xml ``` ### 配置前端控制器 web.xml中配置 ```xml DispatcherServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:spring-mvc.xml DispatcherServlet / ``` ![image-20261104144205116](assets/image-20261104144205116.png) ## 整合Spring、Mybaits 从11 复制代码 注意包 原来com.neuedu.spring 现在com.neuedu.his ![image-20261104153725346](assets/image-20261104153725346.png) ### 依赖 ```xml 4.0.0 com.neuedu.spring spring-learn 1.0 12-springmvc-helloworld war 12-springmvc-helloworld Maven Webapp jakarta.servlet jakarta.servlet-api org.springframework spring-webmvc org.aspectj aspectjweaver org.springframework spring-test org.springframework spring-jdbc org.junit.jupiter junit-jupiter-api com.mysql mysql-connector-j org.mybatis mybatis org.projectlombok lombok com.alibaba druid org.mybatis mybatis-spring ``` ![image-20261104155029369](assets/image-20261104155029369.png) # SpringMVC 的参数绑定 [Method Arguments :: Spring Framework](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/arguments.html) | Controller method argument | Description | | :----------------------------------------------------------- | :----------------------------------------------------------- | | `WebRequest`, `NativeWebRequest` | Generic access to request parameters and request and session attributes, without direct use of the Servlet API. | | `jakarta.servlet.ServletRequest`, `jakarta.servlet.ServletResponse` | Choose any specific request or response type — for example, `ServletRequest`, `HttpServletRequest`, or Spring’s `MultipartRequest`, `MultipartHttpServletRequest`. | | `jakarta.servlet.http.HttpSession` | Enforces the presence of a session. As a consequence, such an argument is never `null`. Note that session access is not thread-safe. Consider setting the `RequestMappingHandlerAdapter` instance’s `synchronizeOnSession` flag to `true` if multiple requests are allowed to concurrently access a session. | | `jakarta.servlet.http.PushBuilder` | Servlet 4.0 push builder API for programmatic HTTP/2 resource pushes. Note that, per the Servlet specification, the injected `PushBuilder` instance can be null if the client does not support that HTTP/2 feature. | | `java.security.Principal` | Currently authenticated user — possibly a specific `Principal` implementation class if known.Note that this argument is not resolved eagerly, if it is annotated in order to allow a custom resolver to resolve it before falling back on default resolution via `HttpServletRequest#getUserPrincipal`. For example, the Spring Security `Authentication` implements `Principal` and would be injected as such via `HttpServletRequest#getUserPrincipal`, unless it is also annotated with `@AuthenticationPrincipal` in which case it is resolved by a custom Spring Security resolver through `Authentication#getPrincipal`. | | `HttpMethod` | The HTTP method of the request. | | `java.util.Locale` | The current request locale, determined by the most specific `LocaleResolver` available (in effect, the configured `LocaleResolver` or `LocaleContextResolver`). | | `java.util.TimeZone` + `java.time.ZoneId` | The time zone associated with the current request, as determined by a `LocaleContextResolver`. | | `java.io.InputStream`, `java.io.Reader` | For access to the raw request body as exposed by the Servlet API. | | `java.io.OutputStream`, `java.io.Writer` | For access to the raw response body as exposed by the Servlet API. | | `@PathVariable` | For access to URI template variables. See [URI patterns](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-requestmapping.html#mvc-ann-requestmapping-uri-templates). | | `@MatrixVariable` | For access to name-value pairs in URI path segments. See [Matrix Variables](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/matrix-variables.html). | | `@RequestParam` | For access to the Servlet request parameters, including multipart files. Parameter values are converted to the declared method argument type. See [`@RequestParam`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/requestparam.html) as well as [Multipart](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/multipart-forms.html).Note that use of `@RequestParam` is optional for simple parameter values. See “Any other argument”, at the end of this table. | | `@RequestHeader` | For access to request headers. Header values are converted to the declared method argument type. See [`@RequestHeader`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/requestheader.html). | | `@CookieValue` | For access to cookies. Cookies values are converted to the declared method argument type. See [`@CookieValue`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/cookievalue.html). | | `@RequestBody` | For access to the HTTP request body. Body content is converted to the declared method argument type by using `HttpMessageConverter` implementations. See [`@RequestBody`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/requestbody.html). | | `HttpEntity` | For access to request headers and body. The body is converted with an `HttpMessageConverter`. See [HttpEntity](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/httpentity.html). | | `@RequestPart` | For access to a part in a `multipart/form-data` request, converting the part’s body with an `HttpMessageConverter`. See [Multipart](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/multipart-forms.html). | | `java.util.Map`, `org.springframework.ui.Model`, `org.springframework.ui.ModelMap` | For access to the model that is used in HTML controllers and exposed to templates as part of view rendering. | | `RedirectAttributes` | Specify attributes to use in case of a redirect (that is, to be appended to the query string) and flash attributes to be stored temporarily until the request after redirect. See [Redirect Attributes](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/redirecting-passing-data.html) and [Flash Attributes](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/flash-attributes.html). | | `@ModelAttribute` | For access to an existing attribute in the model (instantiated if not present) with data binding and validation applied. See [`@ModelAttribute`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.html) as well as [Model](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-modelattrib-methods.html) and [`DataBinder`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-initbinder.html).Note that use of `@ModelAttribute` is optional (for example, to set its attributes). See “Any other argument” at the end of this table. | | `Errors`, `BindingResult` | For access to errors from validation and data binding for a command object (that is, a `@ModelAttribute` argument) or errors from the validation of a `@RequestBody` or `@RequestPart` arguments. You must declare an `Errors`, or `BindingResult` argument immediately after the validated method argument. | | `SessionStatus` + class-level `@SessionAttributes` | For marking form processing complete, which triggers cleanup of session attributes declared through a class-level `@SessionAttributes` annotation. See [`@SessionAttributes`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/sessionattributes.html) for more details. | | `UriComponentsBuilder` | For preparing a URL relative to the current request’s host, port, scheme, context path, and the literal part of the servlet mapping. See [URI Links](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-uri-building.html). | | `@SessionAttribute` | For access to any session attribute, in contrast to model attributes stored in the session as a result of a class-level `@SessionAttributes` declaration. See [`@SessionAttribute`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/sessionattribute.html) for more details. | | `@RequestAttribute` | For access to request attributes. See [`@RequestAttribute`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/requestattrib.html) for more details. | | Any other argument | If a method argument is not matched to any of the earlier values in this table and it is a simple type (as determined by [BeanUtils#isSimpleProperty](https://docs.spring.io/spring-framework/docs/6.2.19/javadoc-api/org/springframework/beans/BeanUtils.html#isSimpleProperty(java.lang.Class))), it is resolved as a `@RequestParam`. Otherwise, it is resolved as a `@ModelAttribute`. | ## @RequestParam 用于访问 Servlet 请求参数,包括多部分文件。参数值 转换为声明的方法参数类型。也请参见[`@RequestParam`](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/requestparam.html) 作为[多部分](https://docs.spring.io/spring-framework/reference/6.2/web/webmvc/mvc-controller/ann-methods/multipart-forms.html)。 注意,对于简单参数值,使用该值是可选的。 参见本表末尾的“其他论证”。`@RequestParam` ``` @ResponseBody //将返回结果转换成json @RequestMapping("/emp/getById") public String getById(@RequestParam("id") int id){ Emp emp = empService.queryById(id); String json = "{\"ename\": \""+ emp.getEname()+"\",\"empno\": \""+ emp.getEmpno()+"\"}"; return json; } ```