Spring
-
官方网址:https://docs.spring.io/
-
官方下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring
-
api:https://docs.spring.io/spring-framework/docs/current/javadoc-api/
-
配置:https://mvnrepository.com/artifact/org.springframework/spring-webmvc/5.3.18
1、概述
- Spring一个开源的免费的框架
- Spring是一个轻量级的、非入侵式的框架
- 控制反转(IOC)、面向切面编程(AOP)
- 支持事务的处理,对框架整合的支持
2、IOC理论推导
- 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。
- 在Spring中实现控制反转的是 IOC 容器,其实现方法是依赖注入
3、HelloSpring
-
配置pom.xml
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.18</version> </dependency>
-
创建实体类
public class Hello { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Hello!" + name ; } }
-
写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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="hello" class="com.wjh.pojo.Hello"> <property name="name" value="Spring"/> </bean> </beans>
-
测试类
//获取Spring的上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //调用Spring中的数据 Hello hello = (Hello) context.getBean("hello"); System.out.println(hello.getName()); Hello Spring
综上可得:
对象是由Spring创建的
依赖注入就是通过set方法注入的
要实现不同的操作,只需要改变xml即可
4、IOC创建对象方式
-
默认的创建方式为 无参构造 【在xml文件被加载的时候,全部对象就已经被初始化了】
-
有参构造
-
通过传入属性索引创建
<bean id="user" class="com.wjh.pojo.User"> <constructor-arg index="0" value="王佳慧"/> <constructor-arg index="1" value="20"/> </bean>
-
通过属性名、值创建
<bean id="user" class="com.wjh.pojo.User"> <constructor-arg name="name" value="王二"/> <constructor-arg name="age" value="21"/> </bean>
-
通过数据类型创建 不推荐!!!
<bean id="user" class="com.wjh.pojo.User"> <constructor-arg type="java.lang.String" value="王二"/> </bean>
-
5、Spring配置
5.1 别名
在之后测试类中调用的时候,可以使用别名,当然也可以仍然使用原来的名字
<bean id="user" class="com.wjh.pojo.User">
<constructor-arg name="name" value="王二"/>
<constructor-arg name="age" value="21"/>
</bean>
<alias name="user" alias="otherName"/>
5.2 Bean配置
<bean id="hello" class="com.wjh.pojo.Hello" name="otherName,otherName2">
<property name="name" value="Spring"/>
</bean>
-
bean
- id 就是自己起的名字,之后在测试类中调用
- class写出具体的实体类地址
- name 就是别名,并且可以起多个
-
property
- name就是实体类的属性名,必须和属性名一模一样
- value就是属性的值
- ref 得到的是Spring创建好的对象
5.3 import
就是将别的xml文件导入到这个xml文件中,形成一个大的xml文件,可以通过调用这个文件调用别的文件
<import resource="bean.xml"/>
6、依赖注入
6.1 构造器注入
<bean id="user" class="com.wjh.pojo.User">
<constructor-arg name="name" value="王二"/>
<constructor-arg name="age" value="21"/>
</bean>
见4、IOC创建对象方式
6.2、Set方式注入
-
依赖注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性由容器来注入
-
实体类
public class Student { private String name; private Address address; private String[] books; private List<String> list; private Map<String,String> map; private Properties info; private Set set; private String testNull; }
-
xml
<bean id="add" class="com.wjh.pojo.Address"> <property name="address" value="address"/> </bean> <bean id="student" class="com.wjh.pojo.Student"> <!--普通值注入--> <property name="name" value="学生"/> <!--bean类型注入--> <property name="address" ref="add"/> <!--数组注入--> <property name="books"> <array> <value>红楼梦</value> <value>水浒传</value> <value>西游记</value> <value>三国演义</value> </array> </property> <!--集合注入--> <property name="list"> <list> <value>list1</value> <value>list2</value> <value>list3</value> </list> </property> <!--Map注入--> <property name="map"> <map> <entry key="key1" value="value1"/> <entry key="key2" value="value2"/> <entry key="key3" value="value3"/> </map> </property> <!--Properties注入--> <property name="info"> <props> <prop key="prop1">prop1</prop> <prop key="prop2">prop2</prop> </props> </property> <!--Set注入--> <property name="set"> <set> <value>set1</value> <value>set2</value> <value>set3</value> </set> </property> <!--测试注入null--> <property name="testNull"> <null/> </property> </bean>
-
测试类
public class DITest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student); } } name='学生', address=address='address, books=[红楼梦, 水浒传, 西游记, 三国演义], list=[list1, list2, list3], map={key1=value1, key2=value2, key3=value3}, info={prop2=prop2, prop1=prop1}, set=[set1, set2, set3], testNull='null
6.3 c、p命名空间注入
-
p命名空间
-
p命名空间相当于 set注入
-
导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
-
xml
<bean id="user" class="com.wjh.pojo.User" p:name="Mike" p:age="25"/>
-
-
c命名空间
-
c命名空间相当于 构造注入
-
导入xml约束
xmlns:c="http://www.springframework.org/schema/c"
-
xml
<bean id="u" class="com.wjh.pojo.User" c:name="John" c:age="21"/>
-
6.4 bean的作用域
-
单例模式 Spring默认的模式
每一 Spring IOC 容器都拥有唯一的实例对象.
<bean id="u" class="com.wjh.pojo.User" c:name="John" c:age="21" scope="singleton"/>
-
原型模式
一个 Bean 定义可以创建任意多个实例对象.
<bean id="u" class="com.wjh.pojo.User" c:name="John" c:age="21" scope="prototype"/>
-
request session application websocket 都是在web开发中才用到
7、Bean自动装配
- 自动装配是Spring满足bean依赖的一种方式
- Spring在上下文中自动寻找,自动给bean装配属性
7.1 byName自动装配
- 通过byName,他会去自动寻找set方法后面的属性名,来进行装配
<bean id="dog" class="com.wjh.pojo.Dog"/>
<bean id="cat" class="com.wjh.pojo.Cat"/>
<bean id="people" class="com.wjh.pojo.People" autowire="byType">
<property name="name" value="Yeah!!!"/>
</bean>
7.1 byType自动装配
<bean class="com.wjh.pojo.Dog"/>
<bean class="com.wjh.pojo.Cat"/>
<bean id="people" class="com.wjh.pojo.People" autowire="byType">
<property name="name" value="Yeah!!!"/>
</bean>
- 通过byName自动装配时,必须保证bean的id是唯一的,并且id名必须和自动注入的属性的Set方法后的值一样
- 通过byType自动装配时,必须保证bean的class是唯一的,并且class必须和自动注入的属性的类型一样
7.3 注解实现自动装配
- @Autowired
-
要实现注解,就要配置好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"> <context:annotation-config/> </beans>
-
在实体类的属性上面添加注解:
@Autowired
- 也可以写在set方法上
- Autowired是先根据byType,然后根据byName
- Autowired要求数据不可以为空,会返回空指针
- 为Autowired添加成:
@Autowired(required = false)
当属性为空的时候,不会报错,会直接输出null
public class People { @Autowired private Dog dog; @Autowired private Cat cat; @Autowired(required = false) private String name; }
<context:annotation-config/> <bean id="cat" class="com.wjh.pojo.Cat"/> <bean id="dog" class="com.wjh.pojo.Dog"/> <bean id="people" class="com.wjh.pojo.People"/>
-
@Qualifier(value = "cat22")
-
添加Qualifier注解后,在xml文件中,id可以写成value的值
@Autowired @Qualifier(value = "cat222") private Cat cat;
<bean id="cat222" class="com.wjh.pojo.Cat"/>
-
8、注解开发
-
依然先配置好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"> <context:component-scan base-package="com.wjh.pojo"/> <context:annotation-config/> </beans>
<context:component-scan base-package="com.wjh.pojo"/>
- 它会将扫描到的包内的注解注册到Spring中,使其发生作用
- 如果扫描到有
@controller、@Service、@Repository、@Component
等注解的java类,就会将这些类注册为bean。 - 如果指定了context:component-scan就不用指定<context:annotation-config/>,前者包含后者。
-
@Component 注入bean
等价于
<bean id="user" class="com.wjh.pojo.User"/>
@Component public class User { public String name = "wjh"; }
-
@Component有几个衍生注解
它们的功能与Component是一样的,都是将 类注册到Spring中
@Repository
用在Dao类- ``@Service ` 用在Service类
@Controller
用在Controller类
-
@Value 属性注入
- 等价于
<property name="name" value="wjh"/>
- 当属性为private的时候,必须要写上set方法,不然取不到
@Component public class User { @Value("wjh") public String name ; }
- 等价于
-
@Autowired 自动装配属性
public class People { @Autowired private Dog dog; @Autowired private Cat cat; @Autowired(required = false) private String name; }
<bean id="cat" class="com.wjh.pojo.Cat"/> <bean id="dog" class="com.wjh.pojo.Dog"/> <bean id="people" class="com.wjh.pojo.People"/>
-
@Nullable 指定的属性可以为空 不报错
-
@Scope 指定作用域
- singleton单例模式 – 全局有且仅有一个实例
- prototype原型模式 – 每次获取Bean的时候会有一个新的实例
9、完全注解开发
- 使用Java完成开发,不再使用xml来配置
- 其实就是创建了一个Config类,代替xml,使用java语句来实现bean注册
MyConfig.java
-
@Configuration 声明一个类为配置类,用于取代bean.xml配置文件注册bean对象
-
@Bean 表示将这个类注册为Bean
@Configuration public class MyConfig { @Bean public User getUser(){ return new User(); } }
实体类
-
@Component 等价于
<bean id="user" class="com.wjh.pojo.User"/>
-
@Value 将属性注册到Spring
@Component public class User { @Value("vdsvds") private String name; public String getName() { return name; } }
测试类
-
用Java代替xml注册之后,创建ApplicationContext使用
AnnotationConfigApplicationContext
-
context.getBean("getUser");
获取类,是传入Config类中的类名ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); User user = (com.wjh.pojo.User) context.getBean("getUser"); System.out.println(user.getName());
10、代理模式
如果要为某个业务增加拓展,但是不能改变原有业务的代码,可以增加一层(代理类)在实现原有业务的基础上,增加业务代码,也就是利用代理模式
10.1静态代理
-
抽象角色
public interface Rent { void rent(); }
-
真实角色
public class Real implements Rent{ public void rent() { System.out.println("真实角色进行"); } }
-
代理角色
public class Proxy implements Rent{ private Real real; public Proxy() { } public Proxy(Real real) { this.real = real; } public void rent() { First(); real.rent(); Second(); } public void First(){ System.out.println("代理角色进行第一步"); } public void Second(){ System.out.println("代理角色进行第三步"); } }
-
测试
public class TestProxy { public static void main(String[] args) { Real real = new Real(); Proxy proxy = new Proxy(real); proxy.rent(); } } 代理角色进行第一步 真实角色进行 代理角色进行第三步
好处:
- 公共业务拓展的时候,方便集中管理
- 可以使真实角色的操作更纯粹,不用关注公共业务
缺点:
- 一个真实角色对应一个代理角色,代码量翻倍,开发效率降低
10.2动态代理
Proxy : 代理类 InvocationHandler : 调用处理程序并返回代理结果
-
抽象角色
public interface Abstract { void test(); }
-
真实角色
public class Real implements Abstract{ public void test() { System.out.println("真实角色操作。。。"); } }
-
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(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName()); return method.invoke(target,args); } public void log(String msg){ System.out.println("执行了"+msg+"方法"); } }
-
测试类
public class Client { public static void main(String[] args) { //真实角色 Real real = new Real(); //代理角色 ProxyInvocationHandler pih = new ProxyInvocationHandler(); //设置需要代理的角色 pih.setTarget(real); //动态生成代理类 Abstract proxy = (Abstract) pih.getProxy(); //调用方法,已经进行了代理处理 proxy.test(); } }
优点:
- 动态代理模式,代理的是抽象角色,是一个接口,可以通过改变传入的真实角色进行代理处理。
- 一个动态代理类代理一个类型的角色,一个动态代理类可以代理多个实现同一接口的角色
- 不需要每一个真实角色都创建一个静态代理类了
11、AOP
导入aop依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8.RELEASE</version>
</dependency>
11.1 Spring API接口
通过Spring的API接口实现代理
-
xml文件导入Aop约束
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> </beans>
-
抽象角色
public interface UserService { void add(); void delete(); void update(); void query(); }
-
真实角色
public class UserServiceImpl implements UserService{ public void add() { System.out.println("增加了一个用户哟~~~"); } }
-
代理角色添加的操作
- 类继承
MethodBeforeAdvice
,表示在target类中的method前面执行这里面的操作
//在方法前增加某个操作 public class Log implements MethodBeforeAdvice { public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName()+" 的 "+method.getName()+" 要被执行咯"); } }
- 类继承`AfterReturningAdvice,表示在target类中的method前面执行这里面的操作
public class Submit implements AfterReturningAdvice { public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName()+" 的 "+method.getName()+" 被执行完成咯"); } }
- 类继承
-
xml文件注册类,来实现代理
- 通过使用aop依赖来完成
- 先将每个类注册到Spring中 再配置Aop
- 配置好Aop之后,就完成了代理类,之后调用方法的时候,就直接输出代理类的结果了
<!--注册bean--> <bean id="userService" class="com.wjh.service.UserServiceImpl"/> <bean id="log" class="com.wjh.log.Log"/> <bean id="submit" class="com.wjh.log.Submit"/> <!--配置Aop--> <aop:config> <!--切入点:expression:表达式,execution表示要执行的位置 修饰词 返回值 类名 方法名 参数--> <aop:pointcut id="pointcut" expression="execution(* com.wjh.service.UserServiceImpl.*(..))"/> <!--执行环绕增加 环绕通知可以在方法调用前后完成自定义的行为--> <!--意思就是将log类加入到切入点pointcut--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="submit" pointcut-ref="pointcut"/> </aop:config>
测试类
public class Client { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); UserService service = (UserService) context.getBean("userService"); service.add(); } }
常见的切点表达式:
-
匹配任意公共方法的执行:
execution(public * *(..))
-
匹配任意以
set
开始的方法:execution(* set*(..))
-
匹配定义了
AccountService
接口的任意方法:execution(* com.xyz.service.AccountService.*(..))
-
匹配定义在
service
包中的任意方法:execution(* com.xyz.service.*.*(..))
-
匹配定义在
service
包和其子包中的任意方法:execution(* com.xyz.service..*.*(..))
11.2 自定义类实现
通过自定义一个类,实现代理的操作,在之后的xml文件中,注册其为切面
-
自定义类
写全代理类的操作
public class DigPointCut { public void Before(){ System.out.println("===方法执行前==="); } public void After(){ System.out.println("===方法执行后==="); } }
-
xml文件
与SpringAPI不同的是,使用了切面,之后还是要注册切点和环绕增加的
<!--注册bean--> <bean id="userService" class="com.wjh.service.UserServiceImpl"/> <bean id="diy" class="com.wjh.diy.DigPointCut"/> <aop:config> <!--自定义切面--> <aop:aspect ref="diy"> <!--切入点--> <aop:pointcut id="point" expression="execution(* com.wjh.service.UserServiceImpl.*(..))"/> <!--代理操作--> <aop:after method="After" pointcut-ref="point"/> <aop:before method="Before" pointcut-ref="point"/> </aop:aspect> </aop:config>
11.3 注解实现代理
-
为xml添加aop注解约束
<aop:aspectj-autoproxy/>
-
自定义类
- @Aspect 将AnnocationPointCut类注册为切面
- @Before(execution(…)) 添加操作,并填入切点
@Component @Aspect public class AnnocationPointCut { @Before("execution(* com.wjh.service.UserServiceImpl.*(..))") public void before(){ System.out.println("===执行前==="); } @After("execution(* com.wjh.service.UserServiceImpl.*(..))") public void After(){ System.out.println("===方法执行后==="); } //环绕增强 @Around("execution(* com.wjh.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp){ System.out.println("环绕前"); try { Object proceed = jp.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } System.out.println("环绕后"); } }
-
测试类
ApplicationContext context = new ClassPathXmlApplicationContext("annocation.xml"); UserService service = (UserService) context.getBean("userService"); service.add(); 环绕前 ===执行前=== 增加了一个用户哟~~~ ===方法执行后=== 环绕后
12、整合Mybatis
与单纯的Mybatis不同的是:
- 核心配置文件完全可以用Spring配置文件代替
- 不再使用Utils类来创建SqlSessionFactory 用xml文件配置代替
- 核心配置文件不再需要配置数据源,用xml的DataSource代替
- 包括其他配置,包括typeAliases、mappers等等
- 可以在核心配置文件留下typeAliases、settings,其他的交给Spring配置文件
- 需要多加一个类来实现sqlSessionTemplate,进而对数据库进行操作
12.1 步骤:
-
导入相关jar包
-
junit
-
mybatis
-
mysql
-
spring
- spring-jdbc 要想Spring能够对数据库进行操作,就要导入这个包
- spring-webmvc
-
aop
-
mybatis-spring
<dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.18</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.18</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.8.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.7</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> <scope>provided</scope> </dependency> </dependencies>
-
-
编写配置文件
-
测试
12.2 sqlSessionTemplate
-
Spring配置文件
<?xml version="1.0" encoding="GBK"?> <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 https://www.springframework.org/schema/context/spring-context.xsd"> </beans>
-
创建一个xml文件,用来进行spring操作
-
配置数据源DataSource
- 代替了mybatis-config.xml中的引入数据库数据
<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&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean>
-
配置sqlSessionFactory
-
代替了MybatisUtil中的创建SqlSessionFactory
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = null; inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
-
将SqlSessionFactory类注册到Spring中
-
将上面创建的dataSource作为属性加入到SqlSessionFactory中
-
将核心配置文件加入到SqlSessionFactory中
-
将Mapper.xml文件加入到SqlSessionFactory中
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--将mybatis-config.xml注册到SqlSessionFactory中--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!--将UserMapper.xml注册到SqlSessionFactory中--> <property name="mapperLocations" value="classpath:com/wjh/dao/*.xml"/> </bean>
-
-
-
配置sqlSessionTemplate
- 因为SQLSessionTemplate类没有set方法,所以只能通过构造器注入
- 将SqlSessionFactory加入到sqlSessionTemplate中
- 现在的sqlSessionTemplate就等于之前的sqlSession,可以完成一切对数据库的操作
<!--配置sqlSessionTemplate--> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean>
-
-
创建一个实现类,继承接口UserMapper,实现方法。
public class UserMapperImpl implements UserMapper{ private SqlSessionTemplate sqlSessionTemplate; public UserMapperImpl(SqlSessionTemplate sqlSessionTemplate) { this.sqlSessionTemplate = sqlSessionTemplate; } public List<User> selectUser(){ UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class); return mapper.selectUser(); } }
-
将实现类注册在xml配置文件中注册到Spring
<bean id="userMapper" class="com.wjh.dao.UserMapperImpl"> <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/> </bean>
-
测试类
public class TestUserMapper { @Test public void selectAll(){ ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml"); UserMapper userMapper = (UserMapper) context.getBean("userMapper"); List<User> users = userMapper.selectUser(); for (User u:users ) { System.out.println(u); } } }
12.3 SqlSessionDaoSupport
-
当实现类继承SqlSessionDaoSupport类的时候,通过
getSqlSession()
方法可以直接获得sqlSession对象 -
不再需要创建SqlSessionTemplate对象,直接调用
getSqlSession()
方法即可public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{ public List<User> selectUser() { return getSqlSession().getMapper(UserMapper.class).selectUser(); } }
13、事务
- 是指一组要么同时执行成功,要么同时执行失败的SQL语句。是数据库操作的一个执行单元
事务的四大特点:
-
原子性:一个事务内的所有操作是一个整体
-
一致性:表示一个事务内,有一个操作失败,那么所有更改多的数据都必须回滚到修改前的状态
-
隔离性:事务只会查看事务修改之前和修改后数据的状态,不会查看中间状态的数据
-
持久性:事务完成之后,对系统的影响是永久的
Spring的声明式事务
MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager
来实现事务管理。
为什么需要事务?
- 如果不配置事务,可能会存在数据提交不一致的情况
- 事务涉及到数据的一致性和完整性
通过AOP实现Spring事务的织入
-
配置声明式事务
- 将数据源加入到事务中
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
-
结合AOP实现事务的织入,配置好事务通知
- 配置事务加入的方法
name="*"
表示对于所有的方法都起作用propagation表示事务的广播
required
表示支持当前事务,如果当前没有事务,就新建一个事务
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
-
配置事务切入
- 先声明aop
- 再加入切点 切点为aop作用的方法
- 最后加入切入的方法
<aop:config> <aop:pointcut id="pointCut" expression="execution(* com.wjh.dao.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/> </aop:config>
要注意【事务切入的包】 事务发生作用的是execution中包内的方法,而不是测试类调用包内方法的方法