速通Spring
尚硅谷2023最新版Spring6课程_bilibili
1 Spring
【强制】Spring是什么?
1) Spring是一款主流的Java EE轻量级开源框架。
轻量级:体积很小,且不需要依赖于其他组件。
2) 狭义的Spring。
Spring Framework。
3) 广义的Spring。
以Spring Framework为核心的Spring技术栈。
4) Spring的核心思想。
提供各种服务,以帮助我们简化基于POJO的Java应用程序开发。
【强制】Spring模块组成。
1) Spring Core。
spring-core、spring-beans、spring-context、spring-expression。
2) Spring AOP。
spring-aop、spring-aspects、spring-instrument。
3) Spring Data Access。
spring-jdbc、spring-orm、spring-oxm、spring-jms、spring-tx。
4) Spring Web。
spring-web、spring-webmvc、spring-websocket、spring-webflux。
5) Spring Message。
spring-messaging。
6) Spring Test。
spring-test。
2 Spring IoC
2.1 概念
【强制】IoC。
1) IoC:Inversion of Control,控制反转,是一种设计思想。
2) IoC的理念。
让别人为你服务。原先是由程序员自己来包办关于对象的一切,现在让IoC Service Provider(IoC服务提供者)来负责。
3) IoC可以给我们带来什么?
用一句话来概括就是,IoC是一种可以帮助我们解耦各业务对象间依赖关系的对象绑定方式。
【强制】DI。
1) DI:Dependency Injection,依赖注入。
和IoC是一回事,只是观察的角度不同。
2) 依赖注入的实现方式。
构造方法注入、setter方法注入。
【强制】IoC容器。
1) IoC容器是Spring对IoC Service Provider的实现。
IoC Service Provider:IoC服务提供者,是一个概念。
IoC Service Provider主要负责管理Java对象的实例化和初始化,控制对象与对象之间的依赖关系。
2) Spring提供了两种容器类型:BeanFactory和ApplicationContext。
BeanFactory是IoC容器的基本实现,提供了 对象创建管理和依赖注入服务 两种特性。
ApplicationContext是BeanFactory的子接口,在BeanFactory的基础上提供了 统一资源加载策略、国际化信息支持、容器内事件发布功能 等高级特性。
我们开发人员可以无脑选择ApplicationContext。
3) ApplicationContext接口的常用实现类。
ClassPathXmlApplicationContext。
FileSystemXmlApplicationContext。
ConfigurableApplicationContext。
WebApplicationContext。
【强制】Bean。
1) IoC容器管理的Java对象称为Spring Bean。
2) bean的作用域。
singleton:在IoC容器中有且仅有一个实例,默认。
prototype:在IoC容器中可以有多个实例,每次获取都返回一个新的实例。
request:在一个请求范围内有效。
session:在一个会话范围内有效。
3) bean的生命周期(简化版本)。
1. 创建bean。
以反射或者CGLIB动态字节码生成方式(默认后者)获得目标类实例。
以BeanWrapper对目标类实例进行包裹,返回BeanWrapper实例。
2. 给bean设置属性(包括Aware相关依赖)。
3. 调用bean的后置处理器-初始化前方法。
执行自定义的BeanPostProcessor.postProcessBeforeInitialization方法。
4. 初始化bean。
执行自定义的init-method。
5. 调用bean的后置处理器-初始化后方法。
执行自定义的BeanPostProcessor.postProcessAfterInitialization方法。
6. 使用bean。
7. 销毁bean。
关闭容器时,执行自定义的destory-method。
2.2 实践
【强制】获取bean。
1) 配置代码。
<bean id="myBean" class="com.mypath.MyBean"></bean>
2) Java代码。
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
// 1.根据ID获取bean
MyBean myBean1 = (MyBean)context.getBean("myBean");
// 2.根据类型获取bean(要求IoC容器中指定类型的bean有且仅有1个)
MyBean myBean2 = context.getBean(MyBean.class);
// 3.根据ID和类型获取bean
MyBean myBean3 = context.getBean("myBean", MyBean.class);
【强制】依赖注入。
1) 构造方法注入。
<bean id="student" class="com.mypath.Student"><constructor-arg index="0" value="llxz"></constructor-arg><constructor-arg index="1" ref="dream"></constructor-arg>
</bean>
<bean id="dream" class="com.mypath.Dream"></bean>
2) setter方法注入。
<bean id="student" class="com.mypath.Student"><property name="name" value="llxz"></property><property name="dream" ref="dream"></property>
</bean>
<bean id="dream" class="com.mypath.Dream"></bean>
【强制】自动绑定。
1) 手动绑定。
使用<constructor-arg>或<property>为bean的属性注入依赖。
2) 自动绑定,也叫自动装配。
通过<bean>的autowire属性,可以指定采用何种类型的自动绑定模式。
Spring提供了5种自动绑定模式:no、byName、byType、constructor、autodetect。默认为no(手动绑定)。
3) 代码示例(byName)。
Student.book自动绑定bean book。
class Student {private Book book;public void setBook(Book book) {this.book = book;}
}class Book {
}
<bean id="student" class="com.mypath.Student" autowire="byName"></bean>
<bean id="book" class="com.mypath.Book"></bean>
【推荐】FactoryBean。
1) 简介。
FactoryBean是Spring提供的一种整合第三方框架的常用机制。配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性配置的类的实例,而是getObject()方法的返回值。工厂模式。
2) MyFactoryBean实现FactoryBean接口。
public class MyFactoryBean implements FactoryBean<MyBean> {@Overridepublic MyBean getObject() throws Exception {return new MyBean();}@Overridepublic class<?> getObjectType() {return MyBean.class;}
}
3) 配置bean。
<bean id="myBean" class="com.mypath.MyFactoryBean"></bean>
4) 获取bean。
ApplicationContext context = new ClassPathXmlApplicationContext("spring-factorybean.xml");
MyBean myBean = (MyBean) context.getBean("myBean");
2.3 基于注解开发
【强制】开启组件扫描。
1) 开启组件扫描。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 开启组件扫描 --><context:component-scan base-package="com.mypath.mypackage"/>
</beans>
2) 组件扫描的目标注解。
component-scan默认扫描的注解类型是@Component。
在@Component 语义基础上细化后的@Repository、@Service、@Controller 也同样可以被component-scan扫描到。
3) 被添加到容器的组件的命名规则。
component-scan在扫描相关类定义并将它们添加到容器时,会根据注解的value属性来生成beanName。默认的命名规则是 将类名首字母小写。
【强制】@Autowired。
1) @Autowired 按照类型匹配进行依赖注入。
类似于byType类型的自动绑定,但它比byType更加灵活,可以标注在属性、方法、构造方法、构造方法参数上。
2) @Autowired 扫描。
IoC容器需要某种方式来了解哪些对象标注了@Autowired,component-scan对此提供了支持。
3) @Qualifier。
如果用byType方式同时找到多个同类型的对象实例,可以使用注解@Qualifier 对依赖注入的条件做进一步限定。
@Qualifier 是byName自动绑定的注解版,可以单独使用,也可以和@Autowired 一起使用。
【强制】@Resource。
1) @Resource 是JDK扩展包提供的注解,更加具有通用性。
除非是JDK 8,否则需要引入依赖。
<dependency><groupId>jakarta.annotation</groupId><artifactId>jakarta.annotation-api</artifactId><version>2.1.1</version>
</dependency>
2) @Resource 默认byName,未指定name时会使用属性名作为name。通过name找不到的话会尝试byType。
3) @Resource 用在属性、setter方法上。
【强制】全注解开发。
全注解开发就是不再使用Spring配置文件了,写一个配置类来代替配置文件。
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan("com.mypath.mypackage")
public class MyConfig {
}
3 Spring AOP
3.1 概念
【强制】AOP。
1) AOP:Aspect-Oriented Programming,面向方面编程。
2) AOP可以给我们带来什么?
使用AOP,我们可以对类似于日志记录和安全检查等系统需求进行模块化的组织。
3) AOP的实现机制。
AOP的实现机制有动态代理、动态字节码增强、自定义类加载器、AOL扩展等。
在Spring AOP中,在目标类实现了一些接口的情况下,使用基于接口的动态代理技术,否则使用基于类的CGLIB动态字节码增强技术。
【强制】动态字节码增强。
通常的class文件都是从Java源代码文件使用Javac编译器编译而成的,但只要符含Java class规范,我们也可以使用ASM或者CGLIB等Java工具库,在程序运行期间,动态构建字节码的class文件。
在此前提下,我们可以为需要织入横切逻辑的模块类在运行期间,通过动态字节码增强技术,为这些系统模块类生成相应的子类,而将横切逻辑加到这些子类中,让应用程序在执行期间使用的是这些动态生成的子类,从而达到将横切逻辑织入系统的目的。
不过,如果需要扩展的类以及类中的实例方法等声明为final的话,则无法对其进行子类化的扩展。
Spring AOP在无法采用动态代理机制进行AOP功能扩展的时候,会使用CGLIB库的动态字节码增强支持来实现AOP的功能扩展。
【强制】AOP基本概念。
1) Joinpoint。
Jointpoint是可以进行织入操作的系统执行点。常见的Joinpoint类型有:方法调用、方法执行、构造方法调用、构造方法执行、字段设置、字段获取、异常处理执行、类初始化。
2) Pointcut。
Pointcut是Jointpoint的表述方式。有点儿像引用。
Pointcut的表述方式有:直接指定Joinpoint所在方法名称、正则表达式、使用特定的Pointcut表述语言。使用得比较普遍的是正则表达式。
3) Advice。
Advice是单一横切关注点逻辑的载体,它代表将会织入到Jointpoint的横切逻辑。如果将Aspect比作OOP中的Class,那么Advice就相当于Class中的Method。
按照Advice在Joinpoint位置执行时机的差异或者完成功能的不同,Advice可以分为:
1. Before Advice:在Joinpoint指定位置之前执行的Advice。
2. After returning Advice:只有在当前Joinpoint处执行流程正常完成后才执行。
3. After throwing Advice:只有在当前Jointpoint处执行过程中抛出异常情况下才执行。
4. After Advice:不管Joinpoint处执行流程是正常终了还是抛出异常都会执行。
5. Around Advice:对附加其上的Joinpoint进行包裹,可以在Joinpoint之前和之后都指定相应的逻辑,甚至于中断或者忽略Joinpoint处原来程序流程的执行。我们常使用的Filter功能就是Around Advice的一种体现。
4) Aspect。
Aspect是对系统中的横切关注点逻辑进行模块化封装的AOP概念实体。
通常情况下,Aspect可以包含多个Pointcut以及相关Advice定义。
5) Weaver。
Weaver是织入器,职责是完成横切关注点逻辑到系统的最终织入。
ProxyFactory类是Spring AOP中最通用的织入器。
6) Target。
符合Pointcut指定的条件,将被织入横切逻辑的对象。
7) AOP各个概念所处的场景。
3.2 实践
【强制】动态代理。
1) 代理模式。
提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来,即解耦。
2) 动态代理代码示例。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;public class Test {public static void main(String[] args) {ProxyFactory factory = new ProxyFactory(new MyInterfaceImpl());MyInterface proxy = (MyInterface) factory.getProxy();proxy.hello("myParam");}
}interface MyInterface {String hello(String s);
}class MyInterfaceImpl implements MyInterface {@Overridepublic String hello(String s) {return "hello world";}
}class ProxyFactory {private Object target;public ProxyFactory(Object target) {this.target = target;}public Object getProxy() {ClassLoader classLoader = target.getClass().getClassLoader();Class<?>[] interfaces = target.getClass().getInterfaces();InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;try {System.out.println("[动态代理][日志] 方法名: " + method.getName());System.out.println("[动态代理][日志] 参数列表:" + Arrays.toString(args));System.out.println("[动态代理][日志] 开始执行");result = method.invoke(target, args);System.out.println("[动态代理][日志] 返回值:" + result);} catch (Exception e) {System.out.println("[动态代理][日志] 异常:" + e.getMessage());} finally {System.out.println("[动态代理][日志] 执行完毕");}return result;}};return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);}
}
【强制】Pointcut表达式。
1) 匹配模式。
execution、within、this、target、args等。
2) execution模式表达式格式。
execution([权限修饰符] [返回类型] [全类名].[方法名]([参数列表]))
权限修饰符、返回类型、全类名、方法名 可以用通配符 * 代替。
全类名、方法名可以部分匹配,如*Service、get*。
参数列表 可以用 .. 代替。
【强制】@AspectJ 形式的Advice。
1) @Before。
2) @AfterReturning。
3) @AfterThrowing。
4) @After。
5) @Around。
【推荐】@AspectJ 形式的Spring AOP。
1) 配置文件bean.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 开启组件扫描 --><context:component-scan base-package="com.mypath"></context:component-scan><!-- 开启aop自动代理 --><bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"><property name="proxyTargetClass" value="true"></property></bean><!-- 基于Schema的aop自动代理 --><!--<aop:aspectj-autoproxy proxy-target-class="true"/>-->
</beans>
2) Java代码。
package com.mypath;import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;public class Test {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");MyTask proxy = (MyTask) context.getBean("myTask");proxy.task1();proxy.tas k2();}
}@Component
class MyTask {public void task1() {System.out.println("task1 执行");}public void task2() {System.out.println("task2 执行");}
}@Aspect
@Component
class PerformanceTraceAspect {private final Logger logger = Logger.getLogger(PerformanceTraceAspect.class);@Pointcut("execution(public void com.mypath.MyTask.task1()) || execution(public void com.mypath.MyTask.task2())")public void pointcut() {}@Around("pointcut()")public Object performanceTrace(ProceedingJoinPoint joinPoint) throws Throwable {String methodName = joinPoint.getSignature().getName();try {logger.info(methodName + " 开始执行");return joinPoint.proceed();} finally {logger.info(methodName + " 执行结束");}}
}
3) 输出。
[02-13 12:42:20] [INFO] [com.mypath.MyAspect:45] task1 开始执行 task1 执行 [02-13 12:42:20] [INFO] [com.mypath.MyAspect:48] task1 执行结束 [02-13 12:42:20] [INFO] [com.mypath.MyAspect:45] task2 开始执行 task2 执行 [02-13 12:42:20] [INFO] [com.mypath.MyAspect:48] task2 执行结束
【推荐】基于Schema的Spring AOP。
1) Java代码。
package com.mypath;import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;public class Test {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");MyTask myTask = (MyTask) context.getBean("myTask");myTask.task();}
}@Component
class MyTask {public void task() {System.out.println("task 执行");}
}@Component
class MyAspect {private final Logger logger = Logger.getLogger(MyAspect.class);public void doBefore(JoinPoint joinPoint) {if (logger.isInfoEnabled()) {logger.info("before method[" + joinPoint.getSignature().getName() + "] execution.");}}public void doAfterReturning(JoinPoint joinPoint) {if (logger.isInfoEnabled()) {logger.info("method[" + joinPoint.getSignature().getName() + "] completed successfully.");}}public void doAfterThrowing(RuntimeException e) {logger.error(ExceptionUtils.getFullStackTrace(e));}public void doAfter() {logger.warn("release system resources, etc.");}public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {StopWatch watch = new StopWatch();try {watch.start();return joinPoint.proceed();} finally {watch.stop();if (logger.isInfoEnabled()) {logger.info(watch);}}}
}
2) 配置文件bean.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.3.xsd"><!-- 开启组件扫描 --><context:component-scan base-package="com.mypath"></context:component-scan><!-- aop配置 --><aop:config><aop:aspect id="myAspect" ref="myAspect" order="2"><aop:pointcut id="privatePointcut" expression="execution(public void com.mypath.MyTask.task())"/><aop:before pointcut-ref="privatePointcut" method="doBefore"/><aop:after-returning pointcut-ref="privatePointcut" method="doAfterReturning"/><aop:after-throwing pointcut-ref="privatePointcut" method="doAfterThrowing" throwing="e"/><aop:after pointcut-ref="privatePointcut" method="doAfter"/><aop:around pointcut-ref="privatePointcut" method="doAround"/></aop:aspect></aop:config>
</beans>
3) 输出。
[02-13 13:22:40] [INFO] [com.mypath.MyAspect:33] before method[task] execution. task 执行 [02-13 13:22:40] [INFO] [com.mypath.MyAspect:60] StopWatch '': running time = 11056500 ns; [] took 11056500 ns = 100% [02-13 13:22:40] [WARN] [com.mypath.MyAspect:49] release system resources, etc. [02-13 13:22:40] [INFO] [com.mypath.MyAspect:40] method[task] completed successfully.
4 事务
【推荐】声明式事务。
事务控制的代码结构基本是确定的,所以框架就可以将固定模式的代码抽取出来,进行封装。
通过配置的方式、由框架实现的事务称为声明式事务。
【推荐】Spring事务属性。
1) 只读。
true/false。
2) 超时。
超时回滚。单位:秒。
3) 回滚策略。
rollbackFor:回滚。
noRollbackFor:不回滚。
4) 隔离级别。
DEFAULT:使用数据库默认的隔离级别。
READ_UNCOMMITTED:读未提交。
READ_COMMITTED:读已提交。
REPEATABLE_READ:可重复读。
SERIALIZABLE:串行化。
5) 传播行为。
REQUIRED:支持当前事务,如果当前没有事务,就新建一个(默认)。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式运行。
MANDATORY:如果当前没有事务,抛出异常。
REQUIRES_NEW:开启一个新的事务,如果有已存在的事务,将已存在的事务挂起。
NOT_SUPPORTED:以非事务方式运行,如果有已存在的事务,将已存在的事务挂起。
NEVER:以非事务方式运行,如果有已存在的事务,抛出异常。
NESTED:如果有已存在的事务,则运行在一个嵌套式事务中。被嵌套的事务可以独立于外层事务进行提交或回滚。
【推荐】事务的全注解实现。
1) 配置事务。
import javax.sql.DataSource;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;@Configuration
@ComponentScan("com.mypath")
@EnableTransactionManagement
public class Test {@Beanpublic DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}
}
2) 使用事务。
使用@Transactional 注解标识类或方法。
5 统一资源加载
开发中。。
6 其他
6.1 反射
【推荐】反射。
1) 获取Class对象。
Class clazz1 = MyClass.class;
Class clazz2 = new MyClass().getClass();
Class clazz3 = Class.forName("com.mypath")
2) 获取构造方法。
// 获取所有的构造方法
Constructor[] constructors1 = clazz2.getDeclaredConstructors();
// 获取所有的public构造方法
Constructor[] constructors2 = clazz2.getConstructors();// 带参数的构造方法, 括号内为参数对应的Class对象列表
Constructor constructor = clazz2.getConsturctor(String.class, int.class);
3) MyClass实例化。
// 如果constructor为private构造方法
// constructor.setAccessible(true);
MyClass myClass = (MyClass)constructor.newInstance("param1", 2);
4) 获取属性。
// 获取所有的属性
Field[] fields1 = clazz1.getDeclaredFields();
// 获取所有的public属性
Field[] fields2 = clazz1.getFields();
5) 获取方法。
// 获取所有的方法
Method[] methods1 = clazz2.getDeclaredMethods();
// 获取所有的public方法
Method[] methods2 = clazz2.getMethods();
6) 执行方法。
// 如果method为private方法
// method.setAccessible(true);
method.invoke("param1", 2);
6.2 Log4j2
【推荐】Log4j2的重要组件。
1) 日志信息的优先级。
日志信息的优先级从低到高有:TRACE(追踪)、DEBUG(调试)、INFO(信息)、WARN(警告)、FATAL(严重错误)。
2) 日志信息的输出目的地。
将日志打到控制台或文件。
3) 日志信息的输出格式。
【推荐】log4j2的使用。
1) 引入依赖。
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.19.0</version>
</dependency>
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j2-impl</artifactId><version>2.19.0</version>
</dependency>
2) 创建配置文件log4j2.xml。
省略。
3) 导包。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
4) 初始化Logger对象。
private Logger logger = LoggerFactory.getLogger(MyClass.class);
5) 打印信息。
logger.info("hello world");
6.3 JdbcTemplate
【推荐】JdbcTemplate的使用。
1) 引入依赖。
<!-- Spring JDBC -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.0.2</version>
</dependency>
<!-- Druid数据源 -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.15</version>
</dependency>
<!-- MySQL驱动 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version>
</dependency>
2) 创建配置文件jdbc.properties。
jdbc.user=roo
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&useSSL=false
jdbc.driver=com.mysql.cj.jdbc.Driver
3) 创建配置文件bean.xml。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd"><!-- 导入外部属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置JDBCTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="druidDataSource"/></bean><!-- 配置数据源 --><bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="url" value="${jdbc.url}"/><property name="driverClassName" value="${jdbc.driver}"/><property name="username" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/></bean>
</beans>
4) 创建测试类。
import java.util.List;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;public class Test {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");JdbcTemplate jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");String insertSql = "INSERT INTO my_table VALUES(?, ?, ?)";Object[] params = { 1, "hello", "world" };jdbcTemplate.update(insertSql, params);String selectSql = "SELECT * FROM my_table";List<Object> list = jdbcTemplate.query(selectSql,new BeanPropertyRowMapper<>(Object.class));System.out.println(list);}
}
【推荐】JdbcTemplate的全注解实现。
import javax.sql.DataSource;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;import com.alibaba.druid.pool.DruidDataSource;@Configuration
@ComponentScan("com.mypath")
public class MySpringConfig {@Bean(name = "jdbcTemplate")public JdbcTemplate getJdbcTemplate(DataSource dataSource) {JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}@Beanpublic DataSource getDataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setUsername("root");dataSource.setPassword("root");dataSource.setUrl("jdbc:mysql://localhost:3306/spring?characterEncoding=utf8&useSSL=false");return dataSource;}
}
相关文章:

速通Spring
尚硅谷2023最新版Spring6课程_bilibili 1 Spring 【强制】Spring是什么? 1) Spring是一款主流的Java EE轻量级开源框架。 轻量级:体积很小,且不需要依赖于其他组件。 2) 狭义的Spring。 Spring Framework。 3) 广义的Spring。 以Spring F…...

【C++】C++入门
一、 C关键字(C98) C有63个关键字(C语言有32个),如下: asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseenummutabl…...

Linux网络技术学习(五)—— 网络设备初始化(I)
文章目录什么时候进行的设备初始化?设备注册和初始化NIC(网卡 Network Interface Card)初始化的基本目标设备与内核之间的交互硬件中断中断类型传送节流方式为了改善效率中断共享IRQ处理函数映射的组织irqaction结构体存储方式什么时候进行的…...

[技术选型] ClickHouse和StarRocks的介绍
文章目录1.ClickHouse介绍2.StarRocks介绍1.ClickHouse介绍 ClickHouse是面向联机分析处理(OLAP)的开源分析引擎。最初由俄罗斯第一搜索引擎Yandex开发,于2016年开源,开发语言为C。由于其优良的查询性能,PB级的数据规…...

算法刷题打卡第90天:表现良好的最长时间段
表现良好的最长时间段 难度:中等 给你一份工作时间表 hours,上面记录着某一位员工每天的工作小时数。 我们认为当员工一天中的工作小时数大于 8 小时的时候,那么这一天就是「劳累的一天」。 所谓「表现良好的时间段」,意味在这…...

Python语言零基础入门教程(十七)
Python 文件I/O 本章只讲述所有基本的 I/O 函数,更多函数请参考Python标准文档。 #### 打印到屏幕 最简单的输出方法是用print语句,你可以给它传递零个或多个用逗号隔开的表达式。此函数把你传递的表达式转换成一个字符串表达式,并将结果写…...

C语言中大小端问题
目录 一、什么是大小端 二、 举个例子 三、大小端演示 四、解释"二"中举例的问题 五、怎么判断是大端还是小端 六、一个题目 一、什么是大小端 大端模式(大端字节序存储):就是高位字节数据存放在内存的低地址端ÿ…...

vue2+微前端qiankun从搭建到部署的实践(主子应用切换;集成vue3+vite3子应用)
一、最终效果 二、微前端(qiankun)介绍及为什么选择用微前端,可以看官网 三、目录结构如下 四、具体配置 一、主应用配置 1、主应用技术栈 Vue-cli4搭建项目Vue2Element-Uiqiankun;Vue2Element-Uiqiankun 2、搭建好主项目&…...

怎么代理微信小程序创业?
随着微信的兴起,小程序已经成为了人们生活中不可或缺的一部分。如果你想要创业的话,那么代理微信小程序是一个不错的选择。本文将为大家介绍怎么代理微信小程序创业。 一、什么是微信小程序 微信小程序是一款专为移动设备使用者而设计的应用。它通过扫…...

今天是情人节呐,我利用Python制作了好多表白的东西,快来吧~
今天是情人节那,有没有现在没有对象的宝子,评论里扣个111哈哈 目录 玫瑰 爱心树 丘比特 多彩气球 阿玥的小课堂 一、情人节的由来 二、情人节的来历和意义 玫瑰 局部代码实现如下: # 花瓣1 turtle.left(150) turtle.circle(-90, 70) …...

【Linux】-- 进程信号(处理、内核)
上篇:【Linux】-- 进程信号(认识、应用)_川入的博客-CSDN博客 目录 信号其他相关常见概念 pending handler block 信号处理的过程 sigset_t sigset_t使用 系统接口 sigpending sigprocmask 捕捉方法 sigaction struct sigactio …...

C/【静态通讯录】
🌱博客主页:大寄一场. 🌱系列专栏:C语言学习笔记 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 前言 往期回顾: C/扫雷 C/N子棋 通讯录作为通讯录地址的书本,当今的通讯录可以涵盖多项…...
万卷书 - 让孩子对自己负责 [The Self-Driven Child]
让孩子对自己负责 The Self-Driven Child - 让你的孩子更加科学合理的掌控自己的生活 简介 《The Self-Driven Child》(2018)解释了我们对孩子的习惯性控制欲,它导致了孩子压力过大、难以合作,以及主观能动性差。本书不提倡这种做法,而是认为我们应该帮助孩子自己做出合适…...
Postman中cookie的操作
在接口测试中,某些接口的调用,需要带入已有Cookie,比如有些接口需要登陆后才能访问。 Postman接口请求使用Cookie有如下两种方式: 1、直接在头域中添加Cookie头域,适用于已经知道请求所用Cookie数据的情况。 2、使用…...

torch.grid_sample
参考: 双线性插值的理论Pytorch grid_sample解析PyTorch中grid_sample的使用方法pytorch中的grid_sample()使用 查阅官方文档,TORCH.NN.FUNCTIONAL.GRID_SAMPLE grid_sample的函数签名如下所示,torch.nn.functional.grid_sample(input, gr…...

前端基于 Docker 的 SSR 持续开发集成环境实践
项目收益 整体开发效率提升20%。加快首屏渲染速度,减少白屏时间,弱网环境下页面打开速度提升40%。 权衡 在选择使用SSR之前,需要考虑以下事项! SSR需要可以运行Node.js的服务器,学习成本相对较高。对于服务器而言&a…...
ARM交叉编译入门及交叉编译第三方库常见问题解析
1. 交叉编译是什么? 交叉编译简单说来,就是编译成果物的地儿不是你运行这个成果物的地儿。最常见的场景,就是我们要编译一个 ARM版本 的可执行程序,但我们编译这个 ARM版本 可执行程序的地方,是在一个 x86_x64 的平台…...
Ruby Web Service 应用 - SOAP4R
什么是 SOAP? 简单对象访问协议(SOAP,全写为Simple Object Access Protocol)是交换数据的一种协议规范。 SOAP 是一种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息。 简单对象访问协议是交换数据的一种协议规范,是一种轻量的、…...

HashMap底层实现原理概述
原文https://blog.csdn.net/fedorafrog/article/details/115478407 hashMap结构 常见问题 在理解了HashMap的整体架构的基础上,我们可以试着回答一下下面的几个问题,如果对其中的某几个问题还有疑惑,那就说明我们还需要深入代码,…...

Linux驱动学习环境搭建
背景常识 一、程序分类 程序按其运行环境分为: 1. 裸机程序:直接运行在对应硬件上的程序 2. 应用程序:只能运行在对应操作系统上的程序 二、计算机系统的层次结构 所有智能设备其实都是计算机,机顶盒、路由器、冰箱、洗衣机、汽…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...