目录
1、简介
-
下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring
-
maven:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.15</version>
</dependency>
- 七大模块:
- 官网介绍:
- Spring Boot
- 一个快速开发的脚手架
- 基于Spring Boot可以快速的开发单个微服务
- 约定大于配置
- Spring Cloud
- SpringCloud是基于SpringBoot实现的
2、IOC理论推导
一个mapper会有很多不同的实现类,比如UserMapper有UserMapperImpl和UserMapperMysqlImpl,但是service层在引入mapper层(new mapper对象)时一般写定,如:
private UserMapper userMapper = new UserMapperMysqlImpl();
但是用户想要service调用另一个mapper实现类UserMapperImpl,这时就需要去改service层代码,改为:
private UserMapper userMapper = new UserMapperImpl();
换一种思维:
在service层调用mapper时,不用显式定义mapper实现类对象,而是给出setter,让用户调用
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
这样,用户调用service层,service对象调用setter,传入想要的mapper实现类对象
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
((UserServiceImpl)userService).setUserMapper(new UserMapperMysqlImpl());
userService.getUser();
}
用户就掌握了主动权。
3、HelloSpring
配置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">
</beans>
<!--使用Spring来创建对象,在Spring这些都称为Bean-->
<bean id="hello" class="com.cc.pojo.Hello">
<property name="str" value="Spring"/>
</bean>
理解为:id=变量名,class=new的对象类型,设置属性str的值为Spring
等价于
Hello hello = new Hello();
hello.setStr("Spring");
eg:
<bean id="mysqlImpl" class="com.cc.mapper.UserMapperMysqlImpl"/>
<bean id="mapperImpl" class="com.cc.mapper.UserMapperImpl"/>
<bean id="userServiceImpl" class="com.cc.service.UserServiceImpl">
<!--ref:引用Spring容器中创建好的对象 value:具体的值,基本数据类型-->
<property name="userMapper" ref="mysqlImpl"/>
</bean>
public class MyTest {
public static void main(String[] args) {
//获取ApplicationContext;拿到Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//需要什么就直接get
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("userServiceImpl");
userServiceImpl.getUser();
}
}
4、IOC创建对象的方式
1、使用无参构造器创建对象,默认
2、假设要使用有参构造器
1.下标赋值
<bean id="hello1" class="com.cc.pojo.Hello">
<constructor-arg index="0" value="学java"/>
</bean>
2.类型赋值 不推荐
<bean id="hello2" class="com.cc.pojo.Hello">
<constructor-arg type="java.lang.String" value="不学java"/>
</bean>
3.直接通过参数名设置
<bean id="hello3" class="com.cc.pojo.Hello">
<constructor-arg name="str" value="cc"></constructor-arg>
</bean>
在配置文件加载的时候,容器中管理的对象就已经初始化了
5、 Spring配置
5.1 别名
<alias name="hello1" alias="hello"/>
5.2 Bean配置
<bean id="hello1" class="com.cc.pojo.Hello" name="hello,h">
name也可以取别名,还能取多个
5.3 import
一般用于团队开发使用,可以将多个配置文件导入合并为一个
假设,三个人开发不同的类,注册在不同的bean中,可以利用import将所有人的beans.xml合并为一个总的。
applicationContext.xml
<import resource="beans.xml"/>
<import resource="beans.xml2"/>
<import resource="beans.xml3"/>
使用的时候,直接使用总配置就可以了
6、依赖注入
6.1 构造器注入
前面已经说过了
6.2 Set方式注入(重点)
- 依赖注入:Set注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性,由容器来注入!
【环境搭建】
1.复杂类型
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
2.真实测试对象
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbies;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
}
3.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="student" class="com.cc.pojo.Student">
<!--第一种,普通值注入,value-->
<property name="name" value="cc"/>
</bean>
</beans>
4.测试类
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}
}
5.完善注入信息
<bean id="address" class="com.cc.pojo.Address">
<property name="address" value="在家"/>
</bean>
<bean id="student" class="com.cc.pojo.Student">
<!--第一种,普通值注入,value-->
<property name="name" value="cc"/>
<!--第二种,Bean注入,ref-->
<property name="address" ref="address"/>
<!--第三种,数组-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>水浒传</value>
<value>三国演义</value>
</array>
</property>
<!--第四种,list-->
<property name="hobbies">
<list>
<value>听歌</value>
<value>敲代码</value>
<value>看电影</value>
</list>
</property>
<!--第五种,Map-->
<property name="card">
<map>
<entry key="身份证" value="12345687654322222222222"/>
<entry key="银行卡" value="11111111154322222222222"/>
</map>
</property>
<!--第六种,Set-->
<property name="games">
<set>
<value>LOL</value>
<value>COC</value>
<value>BOB</value>
</set>
</property>
<!--第七种,空和null-->
<!--<property name="wife" value="">-->
<property name="wife">
<null/>
</property>
<!--第八种Properties-->
<property name="info">
<props>
<prop key="学号">20190525</prop>
<prop key="性别">男</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
6.3 拓展方式注入
p命名空间注入
xmlns:p="http://www.springframework.org/schema/p"
<!--p命名空间注入,可以直接注入属性的值:property-->
<bean id="user" class="com.cc.pojo.User" p:name="cc" p:age="22"/>
c命名空间注入
xmlns:c="http://www.springframework.org/schema/c"
<!--c命名空间注入,可以通过构造器注入:construct-args-->
<bean id="user2" class="com.cc.pojo.User" c:age="18" c:name="cc"/>
注意点:不能直接使用,需要导入xml约束
6.4 bean的作用域
Scope | Description |
---|---|
singleton | (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. |
prototype | Scopes a single bean definition to any number of object instances. |
request | Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext . |
session | Scopes a single bean definition to the lifecycle of an HTTP Session . Only valid in the context of a web-aware Spring ApplicationContext . |
application | Scopes a single bean definition to the lifecycle of a ServletContext . Only valid in the context of a web-aware Spring ApplicationContext . |
websocket | Scopes a single bean definition to the lifecycle of a WebSocket . Only valid in the context of a web-aware Spring ApplicationContext . |
1.单例模式(Spring默认机制)
每次getBean获得的对象指向同一个
<bean id="user2" class="com.cc.pojo.User" c:age="18" c:name="cc" scope="singleton"/>
2.原型模式
每次getBean获得的对象不同
<bean id="user2" class="com.cc.pojo.User" c:age="18" c:name="cc" scope="prototype"/>
3.其余的request、session、application只能在web开发中使用到
7、Bean的自动装配
- 自动装配是Spring满足bean依赖的一种方式
- Spring在上下文中自动在上下文中寻找,并给bean装配属性
在Spring中有三种装配的方式
1.在xml中显式配置
2.在java中显式配置
3.隐式自动装配bean【重要】
7.1 测试
环境搭建
- 一个人有两个宠物
7.2 byName自动装配
<bean id="cat" class="com.cc.pojo.Cat"/>
<bean id="dog" class="com.cc.pojo.Dog"/>
<!--会自动在容器上下文中查找,和自己对象set方法后面的名字对应的bean id-->
<bean id="people" class="com.cc.pojo.People" autowire="byName">
<property name="name" value="cc"/>
</bean>
id和属性名字一致
7.3 byType自动装配
<bean id="cat" class="com.cc.pojo.Cat"/>
<bean id="dog11111" class="com.cc.pojo.Dog"/>
<!--会自动在容器上下文中查找,和自己对象的属性类型相同的bean id-->
<bean id="people" class="com.cc.pojo.People" autowire="byType">
<property name="name" value="cc"/>
</bean>
id可以和属性名字不同,也可以省略
每种类型bean只能有一个
7.4 使用注解实现自动装配
jdk1.5支持的注解,Spring从2.5就支持注解了
要使用注解须知:
1.导入约束 context
2.配置注解的支持 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/>
<bean id="cat" class="com.cc.pojo.Cat"/>
<bean id="dog" class="com.cc.pojo.Dog"/>
<bean id="people" class="com.cc.pojo.People"/>
</beans>
public class People {
@Autowired
private Dog dog;
@Autowired
private Cat cat;
private String name;
-
@Autowired直接在属性上使用,也可以在set方法上使用
-
使用@Autowired可以不用编写set方法,前提是自动装配的属性在IOC(Spring)容器中存在,且符合名字(先byType,后byName,都不行报错,或者给属性加上@Qualifier(value=“指定id”))
-
java注解:@Resource(name = “指定id”),先byName后byType,功能等于@Autowired+@Qualifier(value=“指定id”))
-
@Nullable 被标记的字段可以为null
8、使用注解开发
1.bean
2.属性如何注入
//等价于<bean id="user" class="com.cc.pojo.User"/>
@Component
public class User {
@Value("cc")
public String name;
}
3.衍生的注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
- dao 【@Repository】
- service 【@Service】
- controller 【@Controller】
- 这四个注解功能是一样的,都是代表将某个类注册到容器中,装配Bean
4.自动装配
@Autowired @Resource
5.作用域
@Component
@Scope("singleton")
public class User {
@Value("cc")
public String name;
}
6.小结
xml与注解:
xml更加万能,适用于任何场合,维护简单方便
注解不是自己的类使用不了,维护相对复杂
最佳实践:xml用来管理bean,注解只负责完成属性的注入
必须让注解生效,开启注解支持
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.cc"/>
<context:annotation-config/>
9、使用java的方式配置Spring
我们现在要完全不使用Spring的xml配置了,全权交给java来做!
JavaConfig是Spring的一个子项目,在Spring4之后,它成为了一个核心功能
-
@Configuration:代表这是一个配置类,等价于beans.xml
@Bean:注册一个bean标签,方法名字就相当于id,返回值类型就相当于class,return要注入到bean的对象
@Component :自动装配bean
@ComponentScan:用于配置类,扫描自动装配的类
1.@Configuration+@Bean
@Configuration
public class MyConfig {
@Bean
public User getUser(){
return new User();
}
}
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User getUser = (User) context.getBean("getUser");
System.out.println(getUser.getName());
}
}
2.@Configuration + @ComponentScan +@Component
@Configuration
@ComponentScan("com.cc")
public class MyConfig {
}
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = (User) context.getBean("user");
System.out.println(user.getName());
}
}
- 合并多个配置类
@Configuration
@Import(MyConfig2.class)
public class MyConfig {
@Bean
public User getUser(){
return new User();
}
}
10、代理模式
面试必问【SpringAOP和SpringMVC】
代理模式的分类:
- 静态代理
- 动态代理
10.1 静态代理
角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,一般会做一些附属操作
- 客户:访问代理对象的人
代码步骤:
1、接口
public interface Rent {
public void rent();
}
2、真实角色
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子");
}
}
3、代理角色
public class Proxy implements Rent{
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
@Override
public void rent() {
seeHouse();
host.rent();
sign();
fare();
}
//看房
public void seeHouse(){
System.out.println("中介带你看房");
}
//签合同
public void sign(){
System.out.println("签合同");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
4、客户端访问代理角色
public class Client {
public static void main(String[] args) {
//房东要出租
Host host = new Host();
//中介帮房东租房子,但会有附加操作
Proxy proxy = new Proxy(host);
//中介租房
proxy.rent();
}
}
代理模式的好处:
- 可以使真实角色的操作更加纯粹,不用去关注一些公共业务
- 公共业务交给代理角色,实现了业务分工
- 公共业务发生扩展的时候,方便集中管理
缺点:
一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率变低。
10.2 加深理解
聊聊AOP
10.3 动态代理
- 动态代理和静态代理角色一样
- 动态代理类是动态生成的,不是我们直接写好的
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口—JDK动态代理【我们使用的】
- 基于类–clib
- java字节码实现:javasist
需要了解两个类: Proxy:代理,InvocationHandler:调用处理程序
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object object;
public void setObject(Object object) {
this.object = object;
}
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(),this);
}
//处理代理实例并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
//动态代理的本质就是使用反射机制的实现
Object result = method.invoke(object, 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 handler = new ProxyInvocationHandler();//处理类对象
handler.setObject(userService);//设置要代理的对象
UserService proxy = (UserService) handler.getProxy();//动态生成代理角色
// (代理角色和真实角色平级,都实现了同一个接口,所以强转为接口)
proxy.add();
}
}
动态代理的好处:
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务:比如proxy代理UserService接口,只要给它set不同的UserService实现类对象,就能实现不同业务
11、AOP
导入包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
方式一:使用原生的Spring API接口
比如MethodBeforeAdvice和AfterReturningAdvice
public class Log implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
public class AfterLog implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回值为"+returnValue);
}
}
<!--方式一:使用原生的Spring API接口-->
<!--配置aop:需要导入约束-->
<aop:config>
<!--需要切入点 execution要执行的位置-->
<aop:pointcut id="pointcut" expression="execution(* com.cc.service.UserServiceImpl.*(..))"/>
<!--执行环绕增加-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
public class MyTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理,代理的是接口,不是实现类
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
}
方式二:自定义实现(切面实现)
自定义一个类为切面
public class DiyPointCut {
public void before(){
System.out.println("======方法执行前======");
}
public void after(){
System.out.println("======方法执行后======");
}
}
<bean id="diy" class="com.cc.diy.DiyPointCut"/>
<aop:config>
<!--自定义切面,ref要引用的类-->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="point" expression="execution(* com.cc.service.UserServiceImpl.*(..))"/>
<!--通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
方式三:使用注解实现!
<bean id="annotationPointCut" class="com.cc.diy.AnnotationPointCut"/>
<!--开启注解支持 JDK:默认,proxy-target-class="false" cglib:proxy-target-class="true"-->
<aop:aspectj-autoproxy/>
//使用注解方式实现AOP
@Aspect//标注这个类是一个切面
public class AnnotationPointCut {
@Before("execution(* com.cc.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("======方法执行前======");
}
@After("execution(* com.cc.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("======方法执行后======");
}
//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
@Around("execution(* com.cc.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前");
Signature signature = joinPoint.getSignature();//获得签名
System.out.println(signature);
//执行方法
Object proceed = joinPoint.proceed();
System.out.println("环绕后");
}
}
12、整合Mybatis
步骤:
1.导入jar包
- junit
- mybatis
- mysql数据库
- spring相关
- aop织入
- Mybatis-spring【new】
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</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.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
2.编写配置文件
3.测试
12.1 回忆mybatis
1.编写实体类
2.编写核心配置文件
3.编写接口
4.编写mapper.xml
5.测试
12.2 Mybatis-spring
- 为什么要有实现类?
以前MybatisUtil中实现的:
1.传入配置文件流用SqlSessionFactoryBuilder()获取sqlSessionFactory对象
2.用sqlSessionFactory.openSession()获取sqlSession对象
1、2现在全部注入spring
所以直接从spring的上下文取sqlSession,剩下的操作都一样
SqlSessionTemplate sqlSession = context.getBean("sqlSessionTemplate", SqlSessionTemplate.class);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
如果想一步从spring上下文直接取到mapper呢?
我们知道,mapper作为接口代理,本质是接口实现类,向上转型为接口。(隐藏了编写实现类的过程)
正常来说,注册一个UserMapper的bean,并注入sqlSession就能取到mapper
但,spring不能注入接口,只能注入实现类,所以我们显式定义一个实现类,注入sqlSession
public class UserMapperImpl implements UserMapper{
//注入sqlSession
//所有操作原来都使用sqlSession执行,现在都使用sqlSessionTemplate;
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
注册这个实现类:
<bean id="userMapper" class="com.cc.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSessionTemplate"/>
</bean>
现在:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
List<User> userList = userMapper.selectUser();
下面是完整代码和配置:
UserMapper:
public interface UserMapper {
public List<User> selectUser();
}
spring-dao.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: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">
<!--DataSource:使用Spring的数据源替换Mybatis的配置-->
<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-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--也可以绑定Mybatis配置文件(即各写一部分配置)-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--注册mapper-->
<property name="mapperLocations" value="classpath:com/cc/mapper/*.xml"/>
</bean>
<!--SqlSessionTemplate:就是我们使用的sqlSession-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能使用构造器注入sqlSessionFactory,因为它没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
</beans>
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">
<!--namespace=绑定一个对应的Dao/Mapper接口(类比UserDaoImpl类)-->
<mapper namespace="com.cc.mapper.UserMapper">
<select id="selectUser" resultType="user">
select * from user
</select>
</mapper>
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"
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">
<import resource="spring-dao.xml"/>
<bean id="userMapper" class="com.cc.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSessionTemplate"/>
</bean>
</beans>
UserMapperImpl
public class UserMapperImpl implements UserMapper{
//所有操作原来都使用sqlSession执行,现在都使用sqlSessionTemplate;
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
测试
public class MyTest {
@Test
public void test() throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
SqlSessionTemplate sqlSession = context.getBean("sqlSessionTemplate", SqlSessionTemplate.class);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
List<User> userList = mapper.selectUser();
for (User user : userList) {
System.out.println(user);
}
}
}
12.3 SqlSessionDaoSupport简化操作
直接省略这一步:
<!--SqlSessionTemplate:就是我们使用的sqlSession-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能使用构造器注入sqlSessionFactory,因为它没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
只需要让实现类继承SqlSessionDaoSupport,就可以直接getSession获得session
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
@Override
public List<User> selectUser() {
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
配置时只需要注入sqlSessionFactory
<bean id="userMapper2" class="com.cc.mapper.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
13、声明式事务
spring中的事务管理:
- 声明式事务:aop
- 编程式事务:try catch
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource"/>
<!--或者-->
<!--<property name="dataSource" ref="dataSource"/>-->
</bean>
<!--结合aop实现事务的织入-->
<!--配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--配置事务的传播特性:propagation-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.cc.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>