感谢狂神说java–秦疆老师的教学视频:https://www.bilibili.com/video/BV1WE411d7Dv?p=1
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
1. 简介
- Spring是一个开源免费的框架(容器)!
- Spring是一个轻量级的、非侵入式的框架!
- 控制反转(IOC),面向切面编程(AOP)!
- 支持事务的处理,对框架整合的支持!
总结:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架
拓展
- Spring Boot
- 一个快速开发的脚手架
- 基于SpringBoot可以快速开发单个微服务
- 约定大于配置
- Spring Cloud
- Spring Cloud是基于Spring Boot实现的
2. IOC本质
控制反转IOC(Inversion of Control),是一种设计思想,依赖注入DI(Dependence Inject)是实现IOC的一种方法,也有人认为DI只是IOC的另一种说法,没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象转交给第三方,个人认为所谓的控制反转就是:获得依赖对象的方式反转了。
所谓的IOC,一句话搞定:对象由Spring来创建,管理装配
2.1 配置元数据
基于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="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
- 该
id
属性是标识单个bean定义的字符串。 - 该
class
属性定义Bean的类型,并使用完全限定的类名。
2.2 实例化容器
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml.xml");
3. IOC创建对象的方式
- 使用无参构造创建对象,默认!
- 有参构造创建对象;
-
实体类
@Data @AllArgsConstructor public class User { private String name; public void show() { System.out.println("name=" + name); } }
-
配置ApplicationContext.xml文件
<!--第一种,下标赋值--> <bean id="user" class="com.microsoft.pojo.User"> <constructor-arg index="0" value="李泽玉"/> </bean>--> <!--第二种,参数类型匹配(不推荐使用)--> <bean id="user" class="com.microsoft.pojo.User"> <constructor-arg type="java.lang.String" value="李泽玉"/> </bean> <!--第三种,直接通过参数名来实现--> <bean id="user" class="com.microsoft.pojo.User"> <constructor-arg name="name" value="李泽玉"/> </bean>
-
测试
@Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); User user = context.getBean("user", User.class); user.show(); }
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!
4. Spring配置
4.1 别名
<alias name="user" alias="xidian"/>
4.2 Bean的配置
<!--
id:bean的唯一标识符,也就相当于对象名
class:bean对象所对应的限定名:包名+类型
name:也是别名,而且还可以取多个别名
-->
<bean id="user" class="com.microsoft.pojo.User" name="user2 u2,xidian">
<constructor-arg name="name" value="李泽玉"/>
</bean>
4.3 Import
将多个配置文件合并为一个
5. 依赖注入
5.1 构造器注入
见前 3
5.2 Set方式注入【重点】
- 依赖注入:set注入
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性,由容器来注入
- 实体类
@Data
public class Address {
private String address;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
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;
}
- 注入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="student" class="com.microsoft.pojo.Student">
<!--第一种,普通注入-->
<property name="name" value="李泽玉"/>
<!--第二种,Bean注入,ref-->
<property name="address" ref="address"/>
<!--数组注入,ref-->
<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>
<property name="card">
<map>
<entry key="身份证" value="12345678912313"></entry>
<entry key="银行卡" value="123123123"></entry>
</map>
</property>
<!--Set注入-->
<property name="games">
<set>
<value>LOL</value>
<value>BOB</value>
<value>COC</value>
</set>
</property>
<!--NULL注入-->
<property name="wife">
<null></null>
</property>
<!--Properties注入-->
<property name="info">
<props>
<prop key="学号">201616040220</prop>
<prop key="性别">男</prop>
</props>
</property>
</bean>
<bean id="address" class="com.microsoft.pojo.Address">
<property name="address" value="河南省郑州市"/>
</bean>
</beans>
- 测试
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
Student student = context.getBean("student", Student.class);
System.out.println(student.toString());
}
5.3 拓展方式注入
P命名空间(直接注入)
导入依赖
xmlns:p="http://www.springframework.org/schema/p"
用法
<bean name="user" class="com.microsoft.pojo.User" p:name="李泽玉" p:email="lizeyuwaiting@gmail.com">
C命名空间(需要加入有参构造)
xmlns:c="http://www.springframework.org/schema/c"
5.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 . |
6. Bean的自动装配
- 自动装配是Spring满足Bean依赖的一种方式
- Spring会在上下文中自动寻找,并自动给bean装配属性
在Spring中有三种装配的方式
- 在xml中显式的装配
- 在java中显式配置
- 隐式的自动装配Bean【重要】
6.1 显式装配
<?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="cat" class="com.microsoft.pojo.Cat"></bean>
<bean id="dog" class="com.microsoft.pojo.Dog"></bean>
<bean id="person" class="com.microsoft.pojo.Person">
<property name="name" value="李泽玉"/>
<property name="dog" ref="dog"/>
<property name="cat" ref="cat"/>
</bean>
</beans>
6.2 ByName与ByType自动装配
<bean id="cat" class="com.microsoft.pojo.Cat"></bean>
<bean id="dog" class="com.microsoft.pojo.Dog"></bean>
<!--
ByName:会自动在容器的上下文中查找,和自己对象Set方法后面相对应的bean_id
ByType:会自动在容器的上下文中查找,和自己对象属性类型相同的bean
-->
<bean id="person" class="com.microsoft.pojo.Person" autowire="byName">
<property name="name" value="李泽玉"/>
</bean>
6.3 使用注解自动装配
须知:
- 导入约束
- 配置注解的支持
<?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我们可以不用编写Set方法,==前提是你这个自动装配的属性在IOC容器中存在且符合名字ByName
科普:
@Nullable 字段标记说明这个字段可以为空
@Autowired(required = false) 如果设置为false,该属性可以为null
<bean id="cat11" class="com.microsoft.pojo.Cat"></bean>
<bean id="dog11" class="com.microsoft.pojo.Dog"></bean>
@Autowired依然可以通过ByType找到对应的bean
如果名字为多个,且不同,需加上==@Qualifier(value = “dog11”)==
@Resource与@Autowired【常用】区别:
- @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;
- @Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;
- @Resource注解是由JDK提供,而@Autowired是由Spring提供;
- @Resource和@Autowired都可以书写标注在字段或者该字段的setter方法之上;
7. 使用注解开发
- 配置xml,加入扫描
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.microsoft.pojo"/>
- bean注册与属性注入
@Data
@Component
public class User {
@Value("lizeyu")
private String name;
}
- 衍生的注解
@Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层
-
dao–【@Repository】
-
service–【@Service】
-
controller【@Controller】
这四个注解的功能都是一样的,都是代表某个类注册到Spring中
- 作用域
@Scope
- 小结
xml与注释
- xml更加万能,适用于任何场合,维护简单方便
- 注解不是自己的类使用不了,维护相对复杂
最佳实践
- xml用来管理bean
- 注解只负责完成属性的注入
- 我们在使用过程中只需要注意一个问题,必须让注解生效,就需要开启注解的支持
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.microsoft.pojo"/>
<context:annotation-config/>
8. 使用java的方式配置Spring
我们现在完全不用使用Spring的下xml配置了,全权交给java来做
- 使用配置类注册Bean
@Configuration
public class Config {
public User user;
@Bean
public User getUser() {
return new User();
}
}
- 配置实体类
@Data
@Component
public class User {
@Value("李泽玉")
private String name;
}
- 测试
public class MyText {
@Test
public void test() {
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
User user = context.getBean("getUser", User.class);
System.out.println(user.getName());
}
}
注意:java实现的配置,bean的名字为所注册的函数名
9. 代理模式
9.1 静态代理
- 接口
public interface Rent {
public void rent();
}
- 实现类
public class Host implements Rent {
public void rent() {
System.out.println("房东要出租房子");
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Proxy implements Rent {
private Host host;
public void rent() {
host.rent();
}
}
真实角色和代理角色都可以进行出租功能,在功能上两者一致。房东只做一件事,代理除了出租还可以做其他的服务。
优点:
- 可以使真实的角色的操作更加纯粹,不用去关注一些公众业务
- 公共也就交给代理角色,实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
9.2 动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的!
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口–JDK 动态代理
- 基于类:cglib
- java字节码实现:javasist
需要了解两个类:Proxy,invocationHandler(调用处理程序)
动态代理的好处:
- 可以使真实的角色的操作更加纯粹,不用去关注一些公众业务
- 公共也就交给代理角色,实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
- 一个动态代理类可以代理多个类,只要是实现了同一个接口
实现InvocationHandler
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
@Setter
private Rent rent;
//生成代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
}
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质就是通过反射来实现
Object result = method.invoke(rent, args);
return result;
}
}
测试:
@Test
public void test() {
//真实角色
Host host = new Host();
//代理角色现在没有
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要用的接口对象
pih.setRent(host);
//生成代理类
Rent proxy = (Rent)pih.getProxy();
proxy.rent();
}
10. AOP
10.1 什么是AOP
AOP意为面向切面编程,,通过预编译的方式和运行期动态代理实现程序功能的统一维护的一种技术,AOP是OOP的延续,是软件开发中额一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。
- point(连接点): 类里面可以被增强的方法,这些方法称为连接点
- Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
- Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
- Aspect(切面): 是切入点和通知(引介)的结合
- Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
- Target(目标对象):代理的目标对象(要增强的类)
- Weaving(织入):是把增强应用到目标的过程,把advice 应用到 target的过程
- Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
其实我们只需要这么记忆即可:
- 切入点:在类里边可以有很多方法被增强,比如实际操作中,只是增强了个别方法,则定义实际被增强的某个方法为切入点。
- 通知/增强:增强的逻辑,称为增强,比如扩展日志功能,这个日志功能称为增强。包括:
- 前置通知:在方法之前执行
- 后置通知:在方法之后执行
- 异常通知:方法出现异常执行
- 最终通知:在后置之后执行
- 环绕通知:在方法之前和之后执行
- 切面:把增强应用到具体方法上面的过程称为切面。
10.2 使用Spring实现AOP
【重点】使用AOP织入,需要导入一个依赖包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
方式一:使用Spring的API接口
- 配置文件导入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:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.microsoft.service"/>
<context:component-scan base-package="com.microsoft.log"/>
<context:annotation-config/>
<bean id="userService" class="com.microsoft.service.UserServiceImpl"/>
<bean id="log" class="com.microsoft.log.Log"/>
<!--方式一:使用原生Spring API接口-->
<!--配置AOP,需要导入AOP的约束-->
<aop:config>
<!--切入点 expression:表达式 execution(要执行的位置:* * * * *-->
<aop:pointcut id="pointcut" expression="execution(* com.microsoft.service.UserServiceImpl.*(..))"/>
<!--执行环绕增加 引用log类下的方法,引用切入到切入点-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
</aop:config>
</beans>
- 接口类
public interface UserService {
public void add();
public void delete();
public void update();
public void select();
}
- 实现类
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("增加了一个用户");
}
public void delete() {
System.out.println("删除了一个用户");
}
public void update() {
System.out.println("更新了一个用户");
}
public void select() {
System.out.println("查询了一个用户");
}
}
- 切入类
public class Log implements MethodBeforeAdvice {
//method:要执行的目标对象的方法
//args:参数
//target:目标对象
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName() + "的"+method.getName()+"被执行了");
}
}
- 测试
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
//注意点:采用动态代理的是接口,因此应该转换为接口类
UserService userService = context.getBean("userService", UserService.class);
userService.add();
userService.delete();
userService.update();
userService.select();
}
10.3 自定义类实现AOP
- 配置文件
<bean id="diy" class="com.microsoft.diy.DiyPointCut"/>
<aop:config>
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="point" expression="execution(* com.microsoft.service.UserServiceImpl.*(..))"/>
<!--通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
- 自定义切入面
public class DiyPointCut {
public void before() {
System.out.println("==================方法执行前===========================");
}
public void after() {
System.out.println("==================方法执行后============================" );
}
}
- 测试
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
//注意点:采用动态代理的是接口,因此应该转换为接口类
UserService userService = context.getBean("userService", UserService.class);
userService.add();
userService.delete();
userService.update();
userService.select();
}
10.4 使用注解实现AOP
- 配置文件
<!--方式三:使用注解-->
<bean id="annotationPointCut" class="com.microsoft.diy.AnnotationPointCut"/>
<!--开启注解支持-->
<aop:aspectj-autoproxy/>
- 切面类
//使用注解方式实现AOP
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.microsoft.service.UserServiceImpl.*(..))")
public void before() {
System.out.println("==============方法执行前==============");
}
//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
@Around("execution(* com.microsoft.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint joinPoint) {
//获得签名
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//根据signature获取标记处的方法信息
}
}
- 测试
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
//注意点:采用动态代理的是接口,因此应该转换为接口类
UserService userService = context.getBean("userService", UserService.class);
userService.add();
userService.delete();
userService.update();
userService.select();
}
11.Mybatis-Spring
11.1 安装
要使用 MyBatis-Spring 模块,只需要在类路径下包含 mybatis-spring-2.0.3.jar
文件和相关依赖即可。
如果使用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.3</version>
</dependency>
11.2 步骤
方式一
-
编写数据源配置(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: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:property-placeholder location="db.properties"/> <!--使用Spring管理DataSource,将原mybatis的配置文件中的dataSource省略--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </bean> <!--sqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!--绑定Mybatis配置文件 将原配置文件中的<mapper>标签省略--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/microsoft/mapper/UserMapper.xml"/> </bean> <!--sqlSessionTemplete 就是我们所使用的sqlSession--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <!--因为没有set方法,因此采用构造器注入--> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> </beans>
属性类db.properties
db.driver = com.mysql.cj.jdbc.Driver db.url = jdbc:mysql://localhost:3306/mybatis?useSSl=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC db.username = root db.password = 111111
-
需要给接口加实现类
public class UserMapperImpl implements UserMapper { @Setter private SqlSessionTemplate sqlSession; public List<User> selectUser() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.selectUser(); } }
-
将自己写的实现类注入到Spring中(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:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <import resource="spring-dao.xml"/> <bean id="userMapper" class="com.microsoft.mapper.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"/> </bean> </beans>
-
测试
@Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); UserMapper mapper = context.getBean("userMapper", UserMapperImpl.class); mapper.selectUser(); }
方式二:
SqlSessionDaoSupport
是一个抽象的支持类,用来为你提供 SqlSession
。调用 getSqlSession()
方法你会得到一个 SqlSessionTemplate
,之后可以用于执行 SQL 方法
public class UserMapperImplT extends SqlSessionDaoSupport implements UserMapper{
public List<User> selectUser() {
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
SqlSessionDaoSupport
需要通过属性设置一个 sqlSessionFactory
或 SqlSessionTemplate
。如果两个属性都被设置了,那么 SqlSessionFactory
将被忽略。
<bean id="userMapper" class="com.microsoft.mapper.UserMapperImplT">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
测试
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
UserMapper mapper = context.getBean("userMapper", UserMapperImplT.class);
mapper.selectUser();
}
12. 事务
12.1 回顾事务
- 把一组业务当成一个业务来做:要么都成功,要么都失败
- 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎
- 确保完整性和一致性
事务的ACID原则
- 原子性
- 一致性
- 隔离性
- 多个业务可能操作同一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器中
12.2 Spring中的事务管理
- 声明式事务: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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
<!--结合AOP实现事务的织入-->
<!--配置事务的类-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--配置事务的新特性:new-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* com.microsoft.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
思考:
为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况;
- 如果我们不在SPRING中去配置声明式事务,我们就需要在代码中手动配置事务;
- 事务在项目有开发中十分重要,设计到数据的一致性和完整性问题;
至此spring的基础入门结束,笔者提供一个基于ssm的开发模板,以及一个ssm项目的搭建过程,供大家学习使用
地址:https://github.com/waiting-windy/SSM-Architectural