框架笔记-Spring【待补充】
JavaEE轻量级开元框架,可以整合其他框架。以SpringFramework为核心的框架。
IOC
将对象的创建交给Spring进行创建管理。
SpringIOC是一个容器,对象在容器中进行创建销毁,控制对象与对象之间的依赖关系。
由IOC容器管理的Java对象称为Spring bean,它与关键字new创建的java对象没有任何区别。
控制反转
将创建对象的权利交给第三方容器负责
将对象和对象之间的关系维护交给第三方容器负责
控制反转思想:依赖注入
根据XML方式注入
获取Bean
1、通过bean的id获取
<bean id="user" class="com.zhang.first.entity.User"></bean>
//加载spring配置文件,创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//获取创建对象
User user = (User) ac.getBean("user");//getBean是加载Beanz中的id,创建对象
//操作
user.add();
logger.info("执行完毕");
2、通过类型获取
//加载spring配置文件,创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//获取创建对象
User user = (User) ac.getBean(User.class);//,创建对象
//操作
user.add();
logger.info("执行完毕");
3、根据ID和类型获取
public void testUser3(){
//加载spring配置文件,创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//获取创建对象
User user = (User) ac.getBean("user",User.class);//根据ID和类型获取对象
//操作
user.add();
logger.info("执行完毕");
}
当类型获取bean时,要求IOC容器中指定类型(class)的bean有且只能有一个,不能有两个不同id,相同class的bean存在
<bean id="userDaoImpl" class="com.zhang.first.dao.UserDaoImpl"></bean>
//测试接口声明,实现类实例化
//UserDao userDao = new UserDaoImpl();
//加载spring配置文件,创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//获取创建对象
// UserDao userdao = (UserDao) ac.getBean("userDaoImpl");//getBean通过id获取对象和通过class获取都一样
UserDao userdao = (UserDao) ac.getBean(UserDao.class);
//操作
userdao.add();
logger.info("执行完毕");
当bean里有一个接口有两个接口的实例化对象时,通过类获取就会报错
public void testUser4(){
//加载spring配置文件,创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//获取创建对象
UserDao userdao = (UserDao) ac.getBean("userDaoImpl");//getBean是加载Beanz中的id,创建对象
//操作
userdao.add();
UserDao userdao2 = (UserDao) ac.getBean("personDaoImpl");//getBean是加载Beanz中的id,创建对象
//操作
userdao2.add();
UserDao userdao3 = (UserDao) ac.getBean(UserDao.class);//上述通过BeanId 获取对象没问题,通过类获取就会报错,因为一个接口,不知道实现哪个类
//操作
userdao3.add();
logger.info("执行完毕");
}
Spring创建对象的过程中,将对象的属性值通过配置进行注入
常见的实现方式:
set注入
构造注入
Set注入
entity类中,要有set方法,Bean中可直接设置priperty设置值
<bean id="book" class="com.zhang.first.entity.Book">
<property name="bname" value="前端开发"></property>
<property name="author" value="小张"/>
</bean>
构造注入
<bean id="book2" class="com.zhang.first.entity.Book">
<constructor-arg name="bname" value="开发"></constructor-arg>
<constructor-arg name="author" value="小张"></constructor-arg>
</bean>
BeanFactory工厂 +反射进行实例化
特殊类型注入
如果中间的值为null,则需加null标签
<constructor-arg name="other" ><null></null></constructor-arg>
如果里面有特殊符号,需要转义
<constructor-arg name="other" value="<>"></constructor-arg> <!--里面是特殊符号需要转义-->
特殊符号还可以使用CDATA
<!-- CDATA标识character,里面是纯文本内容,写什么符号都随意-->
<constructor-arg name="other" >
<value>
<![CDATA[a<b]]>
</value>
</constructor-arg>
对象类型注入
引入外部bean:ref引入beanID
<bean id="dept" class="com.zhang.first.entity.Depart">
<property name="name" value="安保部"></property>
</bean>
<!-- 需要引入depart的bean-->
<bean id="empy" class="com.zhang.first.entity.Employee">
<property name="name" value="zhang"></property>
<!-- 注入对象属性:ref表示引入bean为refz值的对象-->
<property name="dept" ref="dept"></property>
</bean>
引入内部bean:
<bean id="dept2" class="com.zhang.first.entity.Depart">
<property name="name" value="财务部"></property>
</bean>
<!-- 需要引入depart的bean-->
<bean id="empy2" class="com.zhang.first.entity.Employee">
<property name="name" value="huang"></property>
<!-- 注入对象属性:ref表示引入bean为refz值的对象-->
<property name="dept">
<bean id="dept2" class="com.zhang.first.entity.Depart">
<property name="name" value="财务部"></property>
</bean>
</property>
</bean>
级联注入:
<!--级联注入-->
<bean id="dept3" class="com.zhang.first.entity.Depart">
<property name="name" value="财务部"></property>
</bean>
<bean id="empy3" class="com.zhang.first.entity.Employee">
<property name="name" value="zhao"></property>
<!-- 注入对象属性:ref表示引入bean为refz值的对象-->
<property name="dept" ref="dept3"></property>
<property name="dept.name" value="测试部"></property> <!-- 此为级联注入-->
</bean>
数组类型注入:
<!--数组类型注入=========================-->
<bean id="dept4" class="com.zhang.first.entity.Depart">
<property name="name" value="财务部"></property>
</bean>
<bean id="empy4" class="com.zhang.first.entity.Employee">
<property name="name" value="zhao"></property>
<!-- 注入对象属性:ref表示引入bean为refz值的对象-->
<property name="dept" ref="dept3"></property>
<property name="dept.name" value="测试部"></property> <!-- 此为级联注入-->
<property name="loves">
<array>
<value>吃饭</value>
<value>睡觉</value>
<value>哈哈</value>
</array>
</property>
</bean>
<!--数组类型注入 ====================-->
注入List集合:
<!--List类型注入=========================-->
<bean id="dept5" class="com.zhang.first.entity.Depart">
<property name="name" value="财务部"></property>
<property name="empy">
<list>
<ref bean="empy5"></ref> <!--将其他的list引入-->
<ref bean="empy6"></ref>
</list>
</property>
</bean>
<bean id="empy5" class="com.zhang.first.entity.Employee">
<property name="name" value="找"></property>
<!-- 注入对象属性:ref表示引入bean为refz值的对象-->
<property name="dept" ref="dept5"></property>
<property name="loves">
<array>
<value>吃饭</value>
<value>睡觉</value>
<value>哈哈</value>
</array>
</property>
</bean>
<bean id="empy6" class="com.zhang.first.entity.Employee">
<property name="name" value="张"></property>
<!-- 注入对象属性:ref表示引入bean为refz值的对象-->
<property name="dept" ref="dept5"></property>
<property name="loves">
<array>
<value>打篮球</value>
<value>攀岩</value>
<value>滑冰</value>
</array>
</property>
</bean>
<!--List类型注入 ====================-->
注入Map集合:
<!-- Map注入================-->
<bean id="tea" class="com.zhang.first.entity.Teacher">
<property name="td" value="11"></property>
<property name="tname" value="张老师"></property>
</bean>
<bean id="tea2" class="com.zhang.first.entity.Teacher">
<property name="td" value="12"></property>
<property name="tname" value="赵老师"></property>
</bean>
<bean id="stu" class="com.zhang.first.entity.Student">
<property name="sid" value="s01"></property>
<property name="sname" value="小梨花"></property>
<property name="teacher">
<map>
<entry>
<key>
<value>11</value>
</key>
<ref bean="tea"></ref>
</entry>
<entry>
<key>
<value>12</value>
</key>
<ref bean="tea2"></ref>
</entry>
</map>
</property>
</bean>
<!-- Map注入================-->
组合注入:使用util,需要引入约束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 组合注入================-->
<bean id="lesson" class="com.zhang.first.entity.Lesson">
<property name="lid" value="l01"></property>
<property name="lname" value="语文"></property>
</bean>
<bean id="lesson2" class="com.zhang.first.entity.Lesson">
<property name="lid" value="l02"></property>
<property name="lname" value="数学"></property>
</bean>
<bean id="tea3" class="com.zhang.first.entity.Teacher">
<property name="td" value="11"></property>
<property name="tname" value="张老师"></property>
</bean>
<bean id="tea4" class="com.zhang.first.entity.Teacher">
<property name="td" value="12"></property>
<property name="tname" value="赵老师"></property>
</bean>
<bean id="stu2" class="com.zhang.first.entity.Student">
<property name="sid" value="s01"></property>
<property name="sname" value="小梨花"></property>
<property name="teacher" ref="teaMap"></property>
<property name="lessons" ref="lessonList"></property>
</bean>
<util:list id="lessonList">
<ref bean="lesson"/>
<ref bean="lesson2"/>
</util:list>
<util:map id="teaMap">
<entry>
<key>
<value>t01</value>
</key>
<ref bean="tea3"></ref>
</entry>
<entry>
<key>
<value>t02</value>
</key>
<ref bean="tea4"></ref>
</entry>
</util:map>
<!-- 组合注入================-->
p命名空间注入
<!-- p命名空间注入==============-->
<bean id="stu3" class="com.zhang.first.entity.Student"
p:sid="s03"
p:sname="小明"
p:lessons-ref="lessonList"
p:teacher-ref="teaMap">
</bean>
<!-- p命名空间注入==============-->
引入外部文件注入
例如设置mysql值
一般用properties,创建spring配置文件,引入context命名空间,引入属性文件,使用表达式
<!--约束-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
新建jdbc.properties
jdbc.username=root
jdbc.password=mysql
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ceshi?serverTimeZone=UTC
在XML文件中引入jdbc.properties路径,注入DruidDataSource
<?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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 引入jdbc.properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
</bean>
</beans>
Scope属性
Bean的作用域:
多实例prototype:获取bean时创建对象
单实例Singleton:默认,IOC容器初始化时创建对象
Bean的生命周期:
Bean对象创建(无参构造)
Bean对象属性赋值
bean后置处理器(初始化前)
Bean初始化
Bean后置处理器(初始化后)
Bean对象创建完成,可以使用
bean对象销毁
IOC容器关闭
FactoryBean
创建实现类,实现FactoryBean方法,可以实现类实例化
public class MyFactoryBean implements FactoryBean<User> {
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
@Override
public User getObject() throws Exception {
return new User();
}
@Override
public Class<?> getObjectType() {
return User.class;
}
}
读取配置文件,即可创建User实例
根据注解方式注入
引入依赖
开启组件扫描
<!-- 自动扫描包-->
<context:component-scan base-package="com.zhang.annotation">
<!-- 排除类不扫描,expression为全类名-->
<context:exclude-filter type="annotation" expression="com.zhang.annotation.entity.User"/>
</context:component-scan>
注解 | 说明 |
---|---|
@Component | 扫描Bean,可以作用在任何层次,Controller、Service、Dao、Entity 等 |
@Repository | 作用在dao层,功能和@Component相同 |
@Service | 作用在Serviceceng ,功能同上 |
@Controller | 作用在Controller层,功能同上 |
@Autowired 根据类型进行装配
@Autowired
private UserDao dao; // 属性注入
private UserDao dao;
@Autowired
public void setDao (UserDao dao){ //Set方法注入
this.dao = dao
}
//构造方法注入
//形参注入
//使用两个注解,使用名称注入,此种方法是一个接口,可能有多个实现类,使用Qualifier可以指定实现类
@Autowired
@Qualifier(value="userRedisDaoImpl")
private UserDao dao;
@Resource
JDK中的,默认根据名称装配,只能用在set方法或属性上,JDK8不需要引入依赖,其他需要引入依赖
<!-- https://mvnrepository.com/artifact/jakarta.annotation/jakarta.annotation-api -->
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
需要在其他注解上声明名称,Resource注解上声明name。如果resource不指定名称,那么根据属性名字进行注入
@Service("myService")
@Resource(name="myServiceImpl")
private UserService service;
@Resource
private UserService service; //没有指定名称,根据service名称匹配@Service("service")的
//@Resource没有指定名称,其他注解也没有指定名称,会根据类型注入
全注解开发
也没有.xml类扫描包了,可以写配置类@Configuration @ComponentScan(“包名”)开启组件扫描
@Configuration
@ComponentScan("com.zhang.annotation") //扫描全包
public class SpringConfig {
}
//测试用配置类配置
@Test
public void test1(){
//加载配置类
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
UserController controller = (UserController) ac.getBean(UserController.class);
controller.run();
}
AOP
面相切面编程。在不改变代码情况下,增强代码功能,加日志,加权限等。通过预编译的方式和运行期动态代理方式实现,在不修改源码情况下,给程序添加额外的功能。代码更灵活,提高了程序的可复用性。
代理模式
代理对象在执行目标方法前后,可以做其他事情,可以将核心代码和非核心代码分离
静态代理
实现了代码的解耦,但是代码都写死了,不具备灵活性
动态代理
AOP底层是动态代理。使用Proxy.newProxyInstance(ClassLoader,interfaces,handle)
引入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>6.0.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.0.11</version>
</dependency>
XML实现AOP
<!--Bean.xml文件-->
<context:component-scan base-package="com.zhang"></context:component-scan>
<!-- 开启自动代理,并为目标对象生成代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Component
@Aspect //切面类
public class LogAspect {
// 切点表达式
// executioin(访问修饰符 增强方法返回值 方法所在类全类名 方法名 (参数参数))
//设置切入点和通知类型
//通知类型:
// 前置通知:@Before(value="切入点表达式配置切入点")
@Before(value="execution(public int com.zhang.CalCulate.*(..))")
public void beforeMethod(){
System.out.println("====前置通知====");
}
// 返回通知:@AfterReturning()
@AfterReturning(value="execution(public int com.zhang.CalCulate.*(..))",returning = "result")
public void afterReturn(JoinPoint joinPoint,Object result){
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("====返回通知====" +methodName +"方法参数:【" + Arrays.toString(args)+"】结果:"+ result+"========");
}
// 异常通知:AfterThrowing()
@AfterThrowing(value="execution(public int com.zhang.CalCulate.*(..))",throwing = "ex")
public void afterThrowing(JoinPoint joinPoint,Object ex){
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("====异常通知====" +methodName +"方法参数:【" + Arrays.toString(args)+"】异常信息:"+ ex+"========");
}
// 后置通知:@After()
@After(value="execution(public int com.zhang.CalCulate.*(..))")
public void after(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("====后置通知====" +methodName +"方法参数:" + Arrays.toString(args)+"========");
}
// 环绕通知:@Around(),在之前之后都会通知
@Around(value="execution(public int com.zhang.CalCulate.*(..))")
public void around(ProceedingJoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("====环绕通知====" +methodName +"方法参数:" + Arrays.toString(args)+"========");
}
}
//测试
@Test
public void test(){
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
CalCulate calculate = (CalCulate) ac.getBean(CalCulate.class);
calculate.add(1,2);
}
重用切面表达式
//重用切面表达式
@Pointcut("execution(public int com.zhang.CalCulate.*(..))")
public void printcut(){}
// 在通知类型value中可以直接value="printcut()"
切面配置在XML文件中,LogAspect类中不用注入@After()@Before()等通知类型了
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.zhang"></context:component-scan>
<!-- 开启自动代理,并为目标对象生成代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<aop:config>
<!-- 配置切面类 -->
<aop:aspect ref="logAspect">
<!-- 配置切入点-->
<aop:pointcut id="pointcut" expression="execution(public int com.zhang.CalCulate.*(..))"/>
<!-- 配置五中通知类型-->
<!-- 前置通知-->
<aop:before method="beforeMethod" pointcut-ref="pointcut"></aop:before>
<!-- 后置通知-->
<aop:after method="after" pointcut-ref="pointcut"></aop:after>
<!-- 返回通知-->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut" returning="result" ></aop:after-returning>
<!-- 异常通知-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="ex"></aop:after-throwing>
<!-- 环绕通知-->
<aop:around method="around" pointcut-ref="pointcut"></aop:around>
</aop:aspect>
</aop:config>
</beans>
模块组成
Spring-core:核心模块:IOC、AOP、Resource
Spring-data-access:JDBC,ORM,OXM
Spring-web:Spring-mvc,Spring-web
Spring-test:对Junit进行集成
实例开发
创建对象的过程:
加载xml文件
对文件解析
获取xml中bean标签的属性值,id-class
通过反射,根据类路径全路径创建对象
将对象放在Map<String,BeanDefinition>beanDefintionMap中,key存放id,BeanDefinition存放对象
引入Spring相关依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>
</dependencies>
创建类,定义属性和方法
构建配置文件,XXX.xml
<!-- 完成对象的创建-->
<!--id:w唯一标识
class:包+类名-->
<bean id="user" class="com.zhang.first.entity.User"></bean>
进行测试
@Test
public void testUser(){
//加载spring配置文件,创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//获取创建对象
User user = (User) ac.getBean("user");//getBean是加载Beanz中的id,创建对象
//操作
user.add();
}
日志log4j
级别
- Trace:最低级别,追踪程序的执行
- Debug: 调试
- info:输出重要信息
- Warn: 警告
- error:错误
- Fatal:严重错误
级别高的会自动屏蔽级别低的日志
操作实例
-
引入依赖
-
在resource下新建log4j2.xml
private Logger logger = LoggerFactory.getLogger(TestUser.class);
<?xml version="1.0" encoding="UTF-8"?>
<configuration >
<loggers>
<!-- 一般从高到低 trace debug info warn error fatal-->
<root level="Debug"> <!-- 级别高的会覆盖级别低的日志,即只输出比定义的级别更高的日志-->
<appender-ref ref="mylog" />
<appender-ref ref="rollingFile" />
<appender-ref ref="myflie" />
</root>
</loggers>
<appenders>
<console name="mylog" target="SYSTEM_OUT"> <!-- 输出信息到控制台-->
<!-- 控制台输出日志格式-->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-3level %logger{1024} -%msg%n ">
</PatternLayout>
</console>
<!-- 文件打印出所有信息,每次运行程序会自动清空,由append属性决定,适合临时测试用-->
<File name="myFile" filename="/Users/nianxinshiyideqiongxiaozi/Desktop/myWorkSpace/mymymy/spring_log/test.log" append="false">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %class{36} %L %M -%msg%xEx%n "/>
</File>
<!-- 可以打印出所有信息,每次超过size 这个size小的日志会自动存入按年份-月份建立的文件夹下进行压缩作为存档-->
<RollingFile name="rollingFile" filename="/Users/nianxinshiyideqiongxiaozi/Desktop/myWorkSpace/mymymy/spring_log/app.log" filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.">
<PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class"></PatternLayout>
<SizeBasedTriggeringPolicy size="50MB"/>
<DefaultRolloverStrategy max="20"></DefaultRolloverStrategy> <!-- 如不设置此属性,则默认为最多同一文件夹下7个文件,这里设置了20-->
</RollingFile>
</appenders>
</configuration>
事务
JDBCTemplate
依赖
<!-- 数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- 数据源-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.11</version>
</dependency>
XML文件
<?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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描全包-->
<context:component-scan base-package="com.zhang"></context:component-scan>
<!-- 引入外部文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClassName" value="${jdbc.driver}"></property>
</bean>
<!-- 创建JDBCTemplate,注入数据源-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="druidDataSource"></property>
</bean>
</beans>
@Autowired
private JdbcTemplate jdbcTemplate;
//添加修改删除
@Test
void run(){
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
User user = (User)ac.getBean(User.class);
//添加
String sql = "insert into t_user values(?,?,?)";
int rows = jdbcTemplate.update(sql,"小明",20,"男");
System.out.println(rows);
}
开启事务
<!-- 注入事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"></property>
</bean>
<!-- 开启事务的注解驱动,通过@transactional所表示的方法或表示类中的方法-->
<tx:annotation-driven transaction-manager="transactionManager"/>
只读:只能查询,不能增删改
@Transantional(ReadOnly=true)
超时:在设置超时时间内没有完成,抛出异常回滚
@Transantional(timeout=3) //3秒超时就回滚
回滚策略:设置哪些异常不会滚
@Transantional(noRollbackFor=ArithmeticException.class) //1/0这样的不回滚
隔离级别:脏读、不可重复度、幻读
全注解开启事务
定义一个Config类,上面@EnableTransactionManagement开启事务管理
import com.alibaba.druid.pool.DruidDataSource;
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 org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@ComponentScan("com.zhang")
@EnableTransactionManagement //开启事务
public class SpringConfig {
//配置数据源
@Bean
public DataSource getDataSource(){
DruidDataSource dds = new DruidDataSource();
dds.setUrl("jdbc:mysql://localhost:3306/ceshi");
dds.setDriverClassName("com.mysql.cj.jdbc.Driver");
dds.setUsername("root");
dds.setPassword("mysql");
return dds;
}
//配置JDBCTemplate
@Bean(name="jdbcTemplate")
public JdbcTemplate getJDBCTemplate(DataSource dataSource){
JdbcTemplate template = new JdbcTemplate();
template.setDataSource(dataSource);
return template;
}
//配置事务
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
return dstm;
}
}