Spring
学习文档:spring中文官网,spring官网
- spring是一个开源的免费框架
- spring是一个轻量级,非入侵式的框架
- 支持事务处理,对框架整合支持
- 重点:控制反转(IOC)和面向切面编程(AOP)
spring就是一个控制反转和面向切面编程的框架(容器)
一、IOC
1.IOC的本质
控制反转loC(Inversion of Control),是一种设计思想,**DI(依赖注入)**是实现loC的一种方法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency Injection,Dl)。
IOC的Hello程序
导入依赖包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.22</version>
</dependency>
//创建一个Hello类
package com.suzezhi.pojo;
public class Hello {
private String name;
public Hello() {
}
public Hello(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Hello{" +
"name='" + name + '\'' +
'}';
}
}
创建一个Spring的配置文件,一般以applicationContext.xml命名(命名随便)
//ApplicationContext.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指定对应的类-->
<bean id="hello" class="com.suzezhi.pojo.Hello">
<property name="name" value="小陈"></property>
</bean>
</beans>
这里要点击右上角,让其加载为配置文件
测试
import com.suzezhi.pojo.Hello;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void testIoc(){
//原来面向对象的写法
// Hello hello = new Hello("小陈");
// System.out.println(hello);
//ioc写法
/*
* 实例化ClassPathXmlApplicationContext来加载配置文件(可以加载多个配置文件)
* 从而获取指定的bean
* 通过bean来操作具体的实现
* */
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) applicationContext.getBean("hello");
System.out.println(hello);
}
}
- Hello 对象是谁创建的?
- hello 对象是由Spring创建的。
- Hello对象的属性是怎么设置的?
- hello 对象的属性是由Spring容器设置的。
这个过程就叫控制反转:
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.
反转:程序本身不创建对象,而变成被动的接收对象.
依赖注入:就是利用set方法来进行注入的.IOC是一种编程思想,由主动的编程变成被动的接收.
可以通过newClassPathXmlApplicationContext去浏览一下底层源码.OK,到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的loC,一句话搞定:对象由Spring来创建,管理,装配!
2. Spring配置
1. bean
bean 定义(definition)本质上是创建一个或多个对象的“配方”。容器在被要求时查看命名的Bean的“配方”,并使用该Bean定义所封装的配置元数据来创建(或获取)一个实际的对象
<bean id="hello" class="com.suzezhi.pojo.Hello" scope="singleton" name="hello2"> <property name="name" value="小陈"></property> </bean>
属性名 | 描述 |
---|---|
id | 相当于Hello的实例对象 |
class | 指定对应的类路径 |
scope | 作用域,默认都是singleton(单例模式) |
name | 为id指定的对象设置别名,可以有多个(通过,或者空格分开),在这里hello与hello2都指向Hello类 |
property | 注入Hello的属性 name指定属性名,基础数据类型:value直接通过以上例子的简写形式赋值;对象类型:使用ref指向注入的bean |
2. import
//ApplicationContext.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">
<!--将其他配置导入-->
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
<!-- 更多bean 定义在这里 -->
<!-- id唯一标识相当于Hello的实例对象,class指定对应的类-->
<bean id="hello" class="com.suzezhi.pojo.Hello">
<property name="name" value="小陈"></property>
</bean>
</beans>
3. IOC依赖注入
在配置文件加载的时候,容器中管理的对象就被初始化了。
方式:构造器注入 和 setter注入
构造器注入方式
方式一:通过使用
type
属性显式地指定构造函数参数的类型,容器就可以使用简单类型的类型匹配
<bean id="hello" class="com.suzezhi.pojo.Hello">
<constructor-arg type="java.lang.String" value="小陈"></constructor-arg>
</bean>
方式二:使用
index
属性来明确指定构造函数参数的索引
<bean id="hello" class="com.suzezhi.pojo.Hello">
<constructor-arg index="0" value="小陈"></constructor-arg>
</bean>
方式三:使用构造函数的参数名称
<bean id="hello" class="com.suzezhi.pojo.Hello">
<constructor-arg name="name" value="小陈"></constructor-arg>
</bean>
setter注入方式
要写属性的set方法,否则无法注入
//把Cat类当作Person类的复杂数据类型
package com.suzezhi.pojo;
public class Cat {
private String name;
public Cat() {
}
public Cat(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
package com.suzezhi.pojo;
import java.util.*;
public class Person {
private String name;
private Cat cat;
private List<String> list;
private String[] arrays;
private Map<String,String> map;
private Set<String> set;
private Properties properties;
public Person(String name, Cat cat, List<String> list, String[] arrays, Map<String, String> map, Set<String> set, Properties properties) {
this.name = name;
this.cat = cat;
this.list = list;
this.arrays = arrays;
this.map = map;
this.set = set;
this.properties = properties;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public String[] getArrays() {
return arrays;
}
public void setArrays(String[] arrays) {
this.arrays = arrays;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", cat=" + cat +
", list=" + list +
", arrays=" + Arrays.toString(arrays) +
", map=" + map +
", set=" + set +
", properties=" + properties +
'}';
}
}
在配置文件注册
<?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">
<!--Cat类-->
<bean id="cat" class="com.suzezhi.pojo.Cat"></bean>
<!-- person类-->
<bean id="person" class="com.suzezhi.pojo.Person">
<!-- 注入相关属性-->
<property name="name" value="小红"></property>
<!-- 注入bean,使用ref-->
<property name="cat" ref="cat"></property>
<!-- 注入list-->
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
<value>list4</value>
</list>
</property>
<!-- 注入数组-->
<property name="arrays">
<array>
<value>西游记</value>
<value>水浒传</value>
<value>红楼梦</value>
<value>三国演义</value>
</array>
</property>
<!-- 注入map-->
<property name="map">
<map>
<entry key="name" value="中国"></entry>
<entry key="name" value="朝鲜"></entry>
</map>
</property>
<!-- set-->
<property name="set">
<set>
<value>set1</value>
<value>set2</value>
<value>set3</value>
</set>
</property>
<!-- propertoes-->
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
</beans>
//测试
import com.suzezhi.pojo.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Person person = (Person) context.getBean("person");
System.out.println(person);
}
}
4.Bean的作用域
Scope | 说明 |
---|---|
singleton | (默认情况下)为每个Spring IoC容器将单个Bean定义的Scope扩大到单个对象实例。 |
prototype | 将单个Bean定义的Scope扩大到任何数量的对象实例。 |
request | 将单个Bean定义的Scope扩大到单个HTTP请求的生命周期。也就是说,每个HTTP请求都有自己的Bean实例,该实例是在单个Bean定义的基础上创建的。只在Web感知的Spring ApplicationContext 的上下文中有效。 |
session | 将单个Bean定义的Scope扩大到一个HTTP Session 的生命周期。只在Web感知的Spring ApplicationContext 的上下文中有效。 |
application | 将单个Bean定义的 Scope 扩大到 ServletContext 的生命周期中。只在Web感知的Spring ApplicationContext 的上下文中有效。 |
websocket | 将单个Bean定义的 Scope 扩大到 WebSocket 的生命周期。仅在具有Web感知的 Spring ApplicationContext 的上下文中有效。 |
5. 自动注入
使用autowire属性将其他bean注册进来
byName
<?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="dog11" class="com.suzezhi.pojo.Dog"></bean>
<bean id="cat" class="com.suzezhi.pojo.Cat"></bean>
<!--
这样不需要我们写<property name="cat" ref="cat"></property>这种引入其他bean的代码
byName:会自动查找和自己在对象上set后面的值对应的beanid,上面的cat能找到(setCat),dog11找不到(setDog)
-->
<bean id="person" class="com.suzezhi.pojo.Person" autowire="byName">
<property name="name" value="小"></property>
</bean>
</beans>
byType
<?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="dog11" class="com.suzezhi.pojo.Dog"></bean>
<bean id="cat" class="com.suzezhi.pojo.Cat"></bean>
<!--
这样不需要我们写<property name="cat" ref="cat"></property>这种引入其他bean的代码
byName:会自动在上下文查找,和自己在对象上set后面的值对应的beanid,上面的cat能找到(setCat),dog11找不到(setDog)
byType:会自动在上下文查找,和自己在对象上类型对应的beanid,上面都可以找到
-->
<bean id="person" class="com.suzezhi.pojo.Person" autowire="byType">
<property name="name" value="小"></property>
</bean>
</beans>
6. 基于注解的方式
- 导入: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:component-scan base-package="com.suzezhi"></context:component-scan>
<context:annotation-config/>
</beans>
package com.suzezhi.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
//相当于xml文件的bean
@Component
public class Person {
//为name赋值
@Value("小陈")
private String name;
//相当于xml文件的<property name="cat" ref="cat"></property>
@Autowired
private Cat cat;
@Autowired
private Dog dog;
public Person(String name, Cat cat, Dog dog) {
this.name = name;
this.cat = cat;
this.dog = dog;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", cat=" + cat +
", dog=" + dog +
'}';
}
}
7. 使用Java配置类
使用java配置类实现全注解方式,不需要写xml配置文件
package com.suzezhi.config;
import com.suzezhi.pojo.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
//设置为配置文件
@Configuration
//扫描包路径
@ComponentScan("com.suzezhi")
//就像 <import/> 元素在Spring XML文件中被用来帮助模块化配置一样,@Import 注解允许从另一个配置类中加载 @Bean 定义
//@Import(ConfigA.class),将configA.class配置文件导入到本配置文件中,外面直接使用本配置文件就可以拿到A的配置信息
public class JavaConfig {
// 相当于<bean id="person" class="com.suzezhi.pojo.Person"></bean>
// 默认情况下,配置类使用 @Bean 方法的名称作为结果Bean的名称。然而,这个功能可以通过 name 属性来重写@Bean("person1")。
@Bean
public Person person() {
return new Person();
}
}
import com.suzezhi.config.JavaConfig;
import com.suzezhi.pojo.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test(){
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
// Person person = applicationContext.getBean("person", Person.class);
// person.getCat().shout();
// person.getDog().shout();
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
Person person = applicationContext.getBean("person", Person.class);
person.getDog().shout();
}
}
二、AOP
AOP是一种横向编程,不需要改变原来的业务逻辑
使用Spring AOP需要导入依赖包
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
1. xml方式
写一个测试业务的类
package com.suzezhi.service;
public class UserServiceImpl {
public void add(){
System.out.println("添加方法");
}
public void del(){
System.out.println("删除方法");
}
public void update(){
System.out.println("更改方法");
}
public void select(){
System.out.println("查询方法");
}
}
创建一个切面类
package com.suzezhi.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
/*这是一个切面*/
public class MyAspect {
/*
* 通知,就是方法
* */
//前置方法
public void before(){
System.out.println("前置方法》》》》》");
}
//后置方法
public void after(){
System.out.println("后置方法》》》》》");
}
// 环绕方法,要有连接点作为参数
public void round(ProceedingJoinPoint joinPoint) throws Throwable {
Object proceed = joinPoint.proceed();
System.out.println("》》环绕方法《《");
}
}
spring的配置文件
引入aop:aspectj-autoproxy/
<?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">
<!-- 引入aop-->
<aop:aspectj-autoproxy/>
<!-- 注册业务类,测试用-->
<bean id="userServiceImpl" class="com.suzezhi.service.UserServiceImpl">
</bean>
<!-- 注册切面类-->
<bean id="myAspect" class="com.suzezhi.aspect.MyAspect"></bean>
<!-- 声明配置aop-->
<aop:config>
<!-- 指定注册的切面,id是标识,ref来自上面注册的切面-->
<aop:aspect id="aspect" ref="myAspect">
<!-- 指定切点,以及接入点(用于那个包) id是切入点的唯一标识,expression里面设置那些路径为连接点,就是要使用aop的-->
<aop:pointcut id="point" expression="execution(* com.suzezhi.service.*.*(..))"/>
<!-- 指定前置方法和后置方法,就是通知,method指定切面类定义的方法,pointcut-ref指定运用到那个切入点上-->
<aop:before method="before" pointcut-ref="point"></aop:before>
<aop:after method="after" pointcut-ref="point"></aop:after>
</aop:aspect>
</aop:config>
</beans>
测试类
import com.suzezhi.service.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test(){
// 加载spring配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取注册的bean
UserServiceImpl userServiceImpl = applicationContext.getBean("userServiceImpl", UserServiceImpl.class);
// 调用对应的方法
userServiceImpl.add();
}
}
测试结果
# 测试里面使用的add方法打印`添加方法`,切面里面定义了前置通知和后置通知,所以add()的内容会被包含在中间
前置方法》》》》》
添加方法
后置方法》》》》》
2. 基于注解方式
使用xml的例子,修改spring配置文件和切面文件
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:aop="http://www.springframework.org/schema/aop"
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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 引入注解-->
<!-- <context:annotation-config/>-->
<!-- 引入aop-->
<aop:aspectj-autoproxy/>
<bean id="userServiceImpl" class="com.suzezhi.service.UserServiceImpl">
</bean>
<!-- 注册切面类-->
<bean id="myAspect" class="com.suzezhi.aspect.MyAspect"></bean>
</beans>
切面文件
package com.suzezhi.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class MyAspect {
/*
* 通知,就是方法
* */
//前置方法
@Before("execution(* com.suzezhi.service.*.*(..))")
public void before(){
System.out.println("前置方法》》》》》");
}
//后置方法
@After("execution(* com.suzezhi.service.*.*(..))")
public void after(){
System.out.println("后置方法》》》》》");
}
// 环绕方法
@Around("execution(* com.suzezhi.service.*.*(..))")
public Object round(ProceedingJoinPoint joinPoint) throws Throwable {
Object proceed = joinPoint.proceed();
System.out.println("》》环绕方法《《");
return proceed;
}
}
三、Spring整合Mybatis(mybatis-spring)
MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
MyBatis-Spring | MyBatis | Spring Framework | Spring Batch | Java |
---|---|---|---|---|
2.0 | 3.5+ | 5.0+ | 4.0+ | Java 8+ |
1.3 | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ |
前置条件:
由于要使用spring,mybatis,mysql(数据库),数据库驱动等等需要使用到这几个依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.22</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.22</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
接下来的步骤跟使用mybatis差不多,我们先做相同点
创建一个user表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) COLLATE utf8_bin NOT NULL,
`password` varchar(30) COLLATE utf8_bin NOT NULL,
`email` varchar(25) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-- 插入数据
insert into user(username,password,email) values('小小','123456','xiao@qq.com'),('大大','123456','da@qq.com')
创建user实体类
package com.suzezhi.pojo;
public class User {
private int id;
private String username;
private String password;
private String email;
public User(int id, String username, String password, String email) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
}
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
}
创建Mapper(或者Dao)接口
package com.suzezhi.mapper;
import com.suzezhi.pojo.User;
import java.util.List;
public interface UserMapper {
//查询用户的方法
List<User> getUserAll();
}
创建映射文件,我创建在resources目录下,包和文件命名与上面的UserMapper保持一致,也可以将映射文件放在mapper接口的同一目录下(需要配置pom.xml文件,使其过滤时包含上mapper目录上的xml文件)
<!-- resources/com/suzezhi/mapper/UserMapper.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--指定命名空间,就是定义的接口类-->
<mapper namespace="com.suzezhi.mapper.UserMapper">
<!-- resultType这里使用别名,在Mybatis核心配置文件设置-->
<select id="getUserAll" resultType="User">
select * from USER ;
</select>
</mapper>
从设置mybatis核心配置文件开始就有所不同了,由于整合mybatis,所以mybatis-config.xml文件我们一般只放起别名和设置(或者全部整合到Spring配置文件中)
<!-- mybatis-config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 配置日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<!-- 起别名-->
<typeAlias type="com.suzezhi.pojo.User" alias="User"></typeAlias>
</typeAliases>
</configuration>
到这里mybatis已配置完成,之前只需将xxxmapper.xml的注册到mybatis-config.xml文件中就可以了
现在由于使用spring整合,需要一个类来注册成组件,所以创建一个UserMapper的实现类(这是不同点)
//UserMapperImpl.java
package com.suzezhi.mapper.impl;
import com.suzezhi.mapper.UserMapper;
import com.suzezhi.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSession;
//设置set方法,用于依赖注入
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List<User> getUserAll() {
//获取mapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userAll = mapper.getUserAll();
return userAll;
}
}
spring的配置文件**,重要:获取sqlSessionFactory对象和注册sqlSession对象 对应的SqlSessionTemplate**
<?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">
<!-- 获取数据源(这里使用jdbc)-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_test?useSSL=false&useUnicode=true&characterEncoding=UTF8"></property>
<property name="username" value="root"></property>
<property name="password" value="134679"></property>
</bean>
<!-- 获取sqlSessionFactory对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 添加数据源-->
<property name="dataSource" ref="dataSource"></property>
<!-- 添加mybatis配置文件-->
<property name="configLocation" value="mybatis-config.xml"></property>
<!-- 添加mapper的映射文件-->
<property name="mapperLocations" value="com/suzezhi/mapper/*.xml"></property>
</bean>
<!-- 注册sqlSession对象 对应的SqlSessionTemplate-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!-- SqlSessionTemplate没有setter,只有构造函数,需要一个sqlSessionFactory对象-->
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!-- 给接口实现类注入sqlSession对象-->
<bean id="userMapperImpl" class="com.suzezhi.mapper.impl.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"></property>
</bean>
</beans>
测试类
public class MyTest {
@Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapperImpl = applicationContext.getBean("userMapperImpl", UserMapperImpl.class);
List<User> userAll = userMapperImpl.getUserAll();
for (User user : userAll) {
System.out.println(user);
}
}
总结差异点
mybatis:
-
mybatis单独使用,数据源配置和xxxmapper.xml文件映射在mybatis-config.xml配置文件中
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test?useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="134679"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/userMapper.xml"></mapper> </mappers> </configuration>
-
通过SqlSessionFactoryBuilder绑定资源创建了SqlSessionFactory,通过SqlSessionFactory对象获取SqlSession
public class MybatisUtil { private static SqlSessionFactory sqlSessionFactory=null; //让以下代码进来就初始化 static { String resource = "mybatis-config.xml"; InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } //返回一个SqlSession对象,操作sql需要用到 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
-
SqlSession绑定接口映射器实现数据库操作
public class TestUserMapper { @Test public void test(){ //获取sqlsession对象 SqlSession sqlSession = MybatisUtil.getSqlSession(); //获取mapper接口类 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //调用方法执行其对应的sql List<User> userList = userMapper.getUserList(); //打印内容 for (User user : userList) { System.out.println(user); } //关闭sqlsession sqlSession.close(); } }
使用数据源配置文件
我们一般会将数据库的相关信息抽出成一个properties文件
db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_test?useSSL=false&useUnicode=true&characterEncoding=UTF8
username=root
password=134679
<!-- applicationContext.xml -->
<!-- 加载数据库配置文件-->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 获取数据源(这里使用jdbc)-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>-->
<!-- <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test?useSSL=false&useUnicode=true&characterEncoding=UTF8"></property>-->
<!-- <property name="username" value="root"></property>-->
<!-- <property name="password" value="134679"></property>-->
<!-- 通过拿db.propperties文件的信息-->
<property name="driverClassName" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
声明式事务管理
使用mybatis时,可以通过SqlSession对象调用commit()进行事务提交,调用rollback()进行事务回滚。
使用spring整合后,我们可以使用Aop切面编程进行事务控制,来是业务处理和事务管控分离。
<!-- 配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 通过AOP实现事务的直入-->
<!-- 配置事务通知-->
<tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
<tx:attributes>
<!-- 配置所有方法都指向事务-->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切入-->
<aop:config>
<!-- com.suzezhi.mapper这个包下的所有方法都执行aop切面操作-->
<aop:pointcut id="txPoint" expression="execution(* com.suzezhi.mapper.*.*(..))"/>
<aop:advisor advice-ref="transactionInterceptor" pointcut-ref="txPoint"></aop:advisor>
</aop:config>