Spring学习笔记
2022/2/1 6:57:47
本文主要是介绍Spring学习笔记,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1、简介
- Spring是一个开源的免费的框架(容器)
- Spring是一个轻量级的、非入侵式的框架
- 控制反转((IOC),面向切面编程(AOP)
- 支持事务的处理,对框架整合的支持
总结一句话: Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架。
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.14</version> </dependency>
2、IOC本质
- 控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法,也有人认为DI只是IOC的另一种说法。没有lOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
- 采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
- 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在 Spring 中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection,Dl)。
3、XML创建实体对象
3.1 创建实体类Hello
package pojo; // 只有无参构造函数 public class Hello { private String str; /* public Hello(String name){ this.str = name; } */ public String getStr() { return str; } public void setStr( String str ) { this.str = str; } @Override public String toString() { return "Hello{" + "str='" + str + '\'' + '}'; } }
3.2 Spring配置文件Beans.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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 无参构造 --> <bean id="hello" class="pojo.Hello"> <!-- value放基本类型 --> <property name="str" value="Spring"/> </bean> <bean id="hello2" class="pojo.Hello2"> <!-- ref放Spring容器中已经创建好的对象 --> <property name="hel" ref="hello"/> </bean> <!-- 有参构造 --> <!-- 第一种,下标赋值 --> <bean id="user" class="com. kuang.pojo.User"> <constructor-arg index="0" value="狂神说Java" /> </bean> <!-- 第二种方式:通过类型创建,不建议使用! --> <bean id="user" class="com. kuang.pojo.user"> <constructor-arg type="java.lang.String" value="ginjiang"/> </bean> <!-- 第三种,直接通过参数名来设置,推荐 --> <bean id="user" class="com.kuang.pojo.User"> <constructor-arg name="name" value="秦疆"/> </bean> </beans>
- 编写完成后记得配置应用程序上下文
3.3 测试运行
import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import pojo.Hello; public class MyTest { @Test public void Test() { // 获取Spring的上下文对象! ApplicationContext context = new ClassPathXmlApplicationContext( "beans.xml" ); // 我们的对象现在都在Spring中的管理了,我们要使用,直接去里面取出来就可以! Hello hello = (Hello) context.getBean( "hello" ); System.out.println( hello.toString() ); //输出:Hello{str='Spring'} } }
4、Spring配置
4.1 别名
- 别名和原名都能够取到对象
<!-- Beans.xml中 --> <!-- 方式1 --> <alias name="user" alias="userNew" />
ApplicationContext context = new ClassPathXmlApplicationContext( "beans.xml" ); // 以下两种均可 Hello hello = (Hello) context.getBean( "user" ); Hello hello = (Hello) context.getBean( "userNew" );
4.2 Bean的配置
<!-- id : bean的唯一标识符,也就是相当于我们学的对象名 class : bean对象所对应的全限定名:包名+类型 name :也是别名,而且name可以同时取多个别名,空格、逗号、分号都能做分隔 --> <bean id="userT" c1ass="com.kuang.pojo.userT" name="user2 u2,u3;u4"> <property name="name" value="西部开源"/> </bean>
4.3 import
这个import,一般用于团队开发使用,他可以将多个配置文件,导入合并为一个配置文件。
假设,现在项目中有多个人开发,这三个人复制不同的类开发,不同的类需要注册在不同的bean中。
我们可以利用import将所有人的beans.xml合并为一个总的!
<import resource="beans1.xml"/> <import resource="beans2.xml"/> <import resource="beans3.xml"/>
使用的时候,使用总的配置就可以了
正式的总配置文件名为applicationContext.xml
5、依赖注入
5.1 构造器注入
见3.2 Spring配置文件Beans.xml
5.2 set方式注入(重点)
public class Student { private String name; private Address address; private String[] books; private List<String> hobbys; private Map<String, string> card; private Set<String>games; private String wife; private Properties info; }
<bean id="student" class="com.kuang.pojo.Student"> <!-- 第一种,普通值注入, value --> <property name="name" value="xx"/> <!-- 第二种,Bean注入,ref --> <property name="address" ref="address" /> <!-- 数组 --> <property name="books"> <array> <value>红楼梦</value> <value>西游记</value> <value>水浒传</value> <value>三国演义</value> </array> </property> <!-- List --> <property name="hobbys"> <list> <value>听歌</value> <value>敲代码</value> <value>看电影</value> </list> </property> <!-- Map --> <property name="card"> <map> <entry key="身份证" value="111111222222223333"/> <entry key="银行卡" value="1321231312312313123"/> </map> </property> <!-- Set --> <property name="games"> <set> <value>LOL</value> <value>coc</value> <value>BOB</value> </set> </property> <!-- null --> <property name="wife"> <nu11/> </property> <!-- 或者 --> <property name="wife" value="" /> <!-- Properties --> <property name="info"> <props> <prop key="driver">xxx</prop> <prop key="ur1">xxx</prop> <prop key="username">root</prop> <prop key="password">123456</prop> </props> </property> </bean>
5.3 拓展方式注入
5.3.1 p命名空间注入
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> <bean id="bar" class="x.y.Bar"/> <!-- p命名空问注入,可以直接注入属性的值: property --> <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost:3306/mydb" p:username="root" p:password="masterkaoli" p:test-ref="bar" /> </beans>
- 注意导入schema:xmlns:p="http://www.springframework.org/schema/p"
5.3.2 C命名空间注入
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="bar" class="x.y.Bar"/> <bean id="baz" class="x.y.Baz"/> <!-- 传统声明 --> <bean id="foo" class="x.y.Foo"> <constructor-arg ref="bar"/> <constructor-arg ref="baz"/> <constructor-arg value="foo@bar.com"/> </bean> <!-- c命名空间声明 --> <bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="foo@bar.com"/> </beans>
- 注意导入schema:xmlns:c="http://www.springframework.org/schema/c"
5.4 Bean的作用域
-
单例模式 Singleton(Spring默认机制)
<bean id="user2" class="pojo.user" c:age="18" scope="singleton" />
-
原型模式 Prototype :每次从容器中getBean的时候,都会产生一个新对象!
<bean id="user2" class="pojo.user" c:age="18" scope="prototype" />
-
其余的request、session、application只能在Web开发中使用到。
6、Bean的自动装配
- 自动装配是 Spring 满足 bean 依赖的一种方式!
- Spring 会在上下文中自动寻找,并自动给 bean 装配属性!
- 在 Spring 中有三种装配的方式
- 在 XML 中显式配置
- 在 Java 中显式配置
- 隐式的自动装配 bean
<!-- 传统注入 --> <beans> <bean id="cat" class="pojo.cat" /> <bean id="dog" class="pojo.Dog" /> <bean id="people" class="com.kuang.pojo.people"> <property name="name" value="xxxx"/> <property name="dog" ref="dog" /> <property name="cat" ref="cat"/> </bean> </beans>
6.1 ByName自动装配
<beans> <bean id="cat" class="pojo.cat" /> <bean id="dog" class="pojo.Dog" /> <!-- byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id --> <bean id="people" class="com.kuang.pojo.people" autowire="byName"> <property name="name" value="xxxx"/> </bean> </beans>
6.2 ByType自动装配
<beans> <bean class="pojo.cat" /> <bean class="pojo.Dog" /> <!-- byType:会自动在容器上下文中查找,和自己对象属性类型(class)相同的bean --> <bean id="people" class="com.kuang.pojo.people" autowire="byType"> <property name="name" value="xxxx"/> </bean> </beans>
小结:
-
byName 的时候,需要保证所有 bean 的 id 存在且唯一,并且这个 bean 需要和自动注入的属性的 set 方法的值一致!
-
byType 的时候,需要保证所有 bean 的 class 存在且唯一,并且这个 bean 需要和自动注入的属性的类型一致!
6.3 使用注解实现自动装配
使用注解须知:
-
导入约束
-
配置注解的支持:<context:annotation-config/>
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 关键所在 --> <context:annotation-config/> <beans> <bean>...</bean> </beans> </beans>
6.3.1 @Autowired
直接在属性上使用!也可以在set方式上使用!
使用@Autowired 我们可以不用编写Set方法了,前提是你这个自动装配的属性Type在 Spring 容器中存在,且符合名字byName!
<beans> <bean id="cat11" class="pojo.cat"/> <bean id="cat111" class="pojo.cat" /> <bean id="dog22" class="pojo.Dog" /> <bean id="dog222" class="pojo.Dog" /> <bean id="people" class="pojo.People" /> </beans>
public class People { @Autowired private cat cat; //@Autowired无法实现时,要配合@qualifier(value="")来针对某一个bean进行装配 @Autowired @Qualifier(value="dog222") private Dog dog; private string name; }
6.3.2 @Resource
public class People { @Resource(name = "cat11") private cat cat; @Resource private Dog dog; }
@Resource 和 @Autowired 的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired 先通过byType的方式实现,后通过byName,而且必须要求这个对象存在!【常用】
- @Resource 默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错!【常用】
小结:
-
@Autowired 先byType,如果同类型个数大于1,再byName。
-
dog只注册了一个的时候,dog的id可以随便取都能自动装配相当于byType。当dog注册了多个时,只能绑定id和person属性名一样的bean相当于byName,如果多个都没有对应的id就报错
-
如果 @Autowired 自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候、我们可以使用@Qualifier(value="xxx") 去配置 @Autowired 的使用,指定一个唯一的bean对象注入!
这个value对应的是bean的id,相当于byName。
7、使用注解开发
在 Spring 4 之后,要使用注解开发。必须要保证 aop 的包导入了!
使用注解需要导入 context 约束,增加注解的支持。
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https: //www.springframework.org/schema/context/spring-context.xsd"> <!-- 指定要扫描的包,这个包下的注解就会生效 --> <context:component-scan base-package="pojo"/> <context:annotation-config/> </beans>
7.1 常用注解
7.1.1 @Autowired
- 通过类型、名字,自动装配
- 如果 @Autowired 不能唯一装配上属性,则需要通过 @Qualifier( value = "xxx" ) 指定唯一bean
7.1.2 @Resource
- 通过名字、类型,自动装配
7.1.3 @Nullable
- 字段标记了这个注解,说明这个字段可以为null
7.1.4 @Component
- 组件,放在类上,说明这个类被 Spring 管理了,成为Bean。
//等价于:<bean id="user" class="pojo.user"/> @Component public class User { public string name; public void setName(string name) { this.name = name; } }
7.1.5 @Value
- @Value( ) 放在属性或set方法上均可。
@component public class User { //相当于 <property name="name" value="kuangshen" /> @Value( "kuangshen2") public string name; public void setName( String name ) { this.name = name; } }
7.1.6 @Scope
@component //确定作用域:单例或原型 @scope("prototype") public class User { public string name; @Value( "kuangshen2") public void setName( String name ) { this.name = name; } }
7.2 衍生的注解
-
@Component有几个衍生注解,我们在web开发中,会按照MVC三层架构分层!
- dao【@Repository】
- service【@Service】
- controller【@Controller】
这四个注解功能都是一样的,都是代表将某个类注册到 Spring 容器中,装配Bean。
8、使用 Java 的方式(注解)配置 Spring
我们现在要完全不使用 Spring 的 XML 配置了,全权交给 Java来做!
JavaConfig 是 Spring 的一个子项目,在 Spring 4 之后,它成为了一个核心功能
package config; import pojo.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; // 这个也会由Spring容器托管,注册到容器中,因为他本来就是一个@Component // @Configuration代表这是一个配置类,就和我们之前看的applicationContext.xml一样 @configuration //相当于<beans> @ComponentScan( "pojo" ) //扫描某个包下的所有@Component @Import(AppConfig2.class) public class AppConfig { // 注册一个bean ,就相当于我们之前写的一个<bean>标签 // 这个方法的名字,就相当于bean标签中的id属性 // 这个方法的返回值,就相当于bean标签中的class属性 @Bean public User user() { return new User(); } }
- 测试
public class MyTest { public static void main(string[] args) { // 如果完全使用了配置类方式去做,我们就只能通过 AnnotationConfig 上下文来获取容器 // 通过配置类的class对象加载! Applicationcontext context = new AnnotationConfigApplicationContext(Appconfig.class); User user = (user) context.getBean("user"); System.out.println(user.getName()); } }
9、代理模式
9.1 静态代理
- 代理对象和真实对象都有共同的接口
- 客户直接通过代理对象直接调用方法
- 在代理类中静态扩展代码
9.2 动态代理
- 动态代理和静态代理角色是一样的。
- 动态代理的代理类是动态生成的,不是我们直接写好的!
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口 —— JDK 动态代理
- 基于类 —— cglib
- Java字节码实现 —— Javassist
需要了解两个类: Proxy:代理 Invocationhandler:调用处理程序
//等我们会用这个类,自动生成代理类! public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private object target; public void setTarget(object target) { this.target = target; } //生成得到代理类 public object getProxy(){ return Proxy.newProxyInstance(this.getclass().getclassLoader(), target.getclass().getInterfaces(), this); } //处理代理实例,并返回结果: public object invoke(0bject proxy,Method method,object[] args) throws Throwable { log(method.getName()); object result = method.invoke(target, args); return result; } public void log(string msg){ system.out.println("执行了" + msg + "方法"); } }
public class client { public static void main( string[ ] args) { //真实角色 (实现类) UserServiceImpl userService = new UserServiceImpl(); //创建代理生成类的实例 ProxyInvocationHandler pih = new ProxyInvocationHandler(); pih.setTarget(userservice); //设置要代理的对象 //代理角色 (动态生成代理类) UserService proxy = (UserService) pih.getProxy(); proxy.query(); } }
动态代理相对于静态代理的好处:
无需编写代理类:对于静态代理,每个类都要写对应的代理类,会多出许多冗余的类;而动态代理,仅需通过一个代理生成类,动态生成对应类的对应代理对象,减少了代码量。
10、AOP
10.1 图解AOP
- 什么叫面向切面编程?这就是:
10.2 Spring 实现 AOP
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency>
10.2.1 使用原生 Spring API
<!-- 注册bean --> <bean id="userService" class="com.kuang.service.UserServiceImpl"/> <!-- com.kuang.log.beforeLog 里面实现了 MethodBeforeAdvice 接口的 before 方法 --> <bean id="beforeLog" class="com.kuang.log.Log"/> <!-- com.kuang.log.afterLog 里面实现了 AfterReturningAdvice 接口的 afterReturning 方法 --> <bean id="afterLog" class="com.kuang.log.AfterLog"/> <!-- 方式一:使用原生Spring API接口 --> <!-- 配置aop:需要导入aop的约束 --> <aop:config> <!-- 切入点: expression:表达式,execution(要执行的位置!* * ***) --> <aop:pointcut id="pointcut" expression="execution(* com.kuang. service.UserServiceImpl.*(..))"/> <!-- 执行环绕增加! --> <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut" /> </aop:config>
10.2.2 自定义类实现
<!-- applicationContext.xml --> <bean id="diy" class="com.kuang.diy.DiyPointCut" /> <aop:config> <!-- 自定义切面, ref要引用的类 --> <aop:aspect ref="diy" > <!-- 切入点 --> <aop:pointcut id="point" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <!-- 通知 --> <aop:before method="before" pointcut-ref="point" /> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config>
10.2.3 注解实现AOP
<bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut" /> <!-- 开启注解支持! --> <aop:aspectj-autoproxy />
//方式三:使用注解方式实现AOP import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; @Aspect //标注这个类是一个切面 public class AnnotationPointcut { @Before( "execution(* com.kuang.service.UserServiceImpl.*(..))") public void before(){ system.out.println( "=======方法执行前======" ); } @After( "execution(* com.kuang.service.UserServiceImpl.*(..))") public void after(){ system.out.println( "=======方法执行后======" ); } // 在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点; // 可以获取切入点的相关信息。 @Around( "execution(*com.kuang.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable { system.out.println("环绕前"); object proceed = jp.proceed(); //执行方法 system.out.println("环绕后"); } }
10.3 Spring AOP 五大通知
-
Before 前置通知
-
AfterReturning 后置通知
-
Around 环绕通知
-
AfterThrowing 异常通知
-
After 最终通知
五种通知的执行顺序
在目标方法没有抛出异常的情况下
前置通知 → 环绕通知的调用目标方法之前的代码 → 目标方法 → 环绕通知的调用目标方法之后的代码 →
后置通知 → 最终通知
在目标方法抛出异常的情况下
前置通知 → 环绕通知的调用目标方法之前的代码 → 目标方法 → 抛出异常 异常通知 → 最终通知
11、整合Mybatis
详细内容可以查看文档
11.1 基础方式
-
导入相关Jar包
- Junit
- Mybatis
- MySQL数据库
- Spring 相关
- AOP 织入
- mybatis-spring 【new】
-
编写 Spring 、Mybatis 配置文件
<!-- spring-dao.xml --> <!-- 数据库的配置,一般不改,直接import进 Spring 的总配置文件 --> <?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- DataSource:使用Spring的数据源替换Mybatis的配置 c3p0 dbcp druid 我们这里使用Spring提供的JDBC:org.springframework.jdbc.datasource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value "jdbc:mysql://localhost:3306/mybatis?useSSL=true"/> <property name="username" value="root" /> <property name="password" value="123456"/> </bean> <!-- sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="datasource" ref="datasource"/> <!-- 绑定Mybatis配置文件 --> <property name="configLocation" value="classpath:mybatis-config.xml" /> <property name="mapperLocations" value="classpath:com/kuang/mapper/*.xml"/> </bean> <!-- sqlSessionTemplate:就是我们使用的sqlSession --> <bean id="sqlSession" class="org.mybatis.spring.sqlsessionTemplate"> <!-- 只能使用构造器注入sqlSessionFactory,因为它没有set方法 --> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean> </beans>
<!-- appplicationContext.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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <import resource="spring-dao.xml"/> <!-- Mapper的实现类 --> <bean id="userMapper" class="com.kuang.mapper.UserMapperImpl"> <property name="sqisession" ref="sqlsession" /> </bean> </beans>
-
写 Mapper.xml(sql语句)
......
-
写 Mapper 的实现类 MapperImpl
import org.mybatis.spring.sqlSessionTemplate; import java.util.List; public class UserMapperImpl implements UserMapper { private sqlsessionTemplate sqlsession; public void setSqlSession(sqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; } public List<User> selectUser() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.selectuser(); } }
11.2 SqlSessionDaoSupport
- 实现类去掉属性 sqlSession 和 set 方法
- 直接通过getSqlSession()获取sqlSession,无需注入依赖
import org.mybatis.spring.sqlSessionTemplate; import java.util.List; public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper { public List<User> selectUser() { return getSqlSession().getMapper(UserMapper.class).selectuser(); } }
同时,在 spring-dao.xml 中去掉:
<!-- sqlSessionTemplate:就是我们使用的sqlSession --> <bean id="sqlSession" class="org.mybatis.spring.sqlsessionTemplate"> <!-- 只能使用构造器注入sqlSessionFactory,因为它没有set方法 --> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean>
并修改:
<!-- Mapper的实现类 --> <bean id="userMapper" class="com.kuang.mapper.UserMapperImpl"> <property name="sqisession" ref="sqlsession" /> </bean> <!-- 修改为 --> <bean id="userMapper" class="com.kuang.mapper.UserMapperImpl"> <!-- 父类 SqlSessionDaoSupport 需要 sqlSessionFactory工厂实例 --> <property name="sqlSessionFactory" ref="sqlsessionFactory" /> </bean>
12、事务
12.1 什么叫事务?
- 把一组业务当成一个业务来做;要么都成功,要么都失败!
- 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎!·确保完整性和一致性;
- 事务ACID原则:
- 原子性:一个事务要么全部执行,要么不执行。
- 一致性:数据库事务不能破坏关系数据的完整性及业务逻辑上的一致性。
- 隔离性:多个业务可能操作同一个资源,防止数据损坏。
- 持久性:事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器中。
12.2 Spring 事务管理
- 声明式事务:AOP
- 编程式事务:需要在代码中,进行事务的管理
为什么需要事务?
如果不配置事务,可能存在数据提交不一致的情况。
如果我们不在 Spring 中去配置声明式事务,我们就需要在代码中手动配置事务!
事务在项目的开发中十分重要,设计到数据的一致性和完整性问题,不容马虎!
12.3 Spring 声明式事务
<!-- spring-dao.xml --> <!--配置声明式事务--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 结合AOP实现事务的织入 --> <!-- 配置事务通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 给哪些方法配置事务(需要结合事务的方法丢进去) --> <!-- 配置事务的传播特性: propagation --> <tx:attributes> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED" /> <tx:method name="query" read-only="true" /> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 配置事务切入 --> <aop:config> <aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" /> </aop:config>
这篇关于Spring学习笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)
- 2024-05-30【Java】百万数据excel导出功能如何实现
- 2024-05-30我们小公司,哪像华为一样,用得上IPD(集成产品开发)?
- 2024-05-30java excel上传--poi
- 2024-05-30安装笔记本应用商店的pycharm,再安排pandas等模块,说是没有打包工具?
- 2024-05-29java11新特性
- 2024-05-29哪些无用敏捷指标正在破坏敏捷转型?
- 2024-05-29鸿蒙原生应用再新丁!新华社 入局鸿蒙
- 2024-05-29设计模式 之 迭代器模式(Iterator)