一、Spring框架
1、简介
spring最大的功能就是控制反转(IOC)、面向切面编程(AOP)!
支持事务的处理,对框架整合的支持!
2、组成
Spring是一个分层框架,它有七个模块组成;每个模块可以相互独立存在于项目中,同时每个模块又可以被其他第三方的框架兼容使用;
Spring的7大模块分别为:spring Core、Spring Context、Spring AOP、Spring ORM、Spring Dao、Spring MVC、spring web,其框架结构如下图所示:
3、拓展
Spring Boot
- 一个快速开发的脚手架
- 基于spring boot可以快速的开发单个微服务
- 约定大于配置!
Spring cloud
- springcloud是基于spring boot实现的
因为大多数公司都在使用spring boot进行快速开发,学习spring boot前提,需要完全掌握spring及Spring MVC!承上启下的作用!
4、spring入门案例
1、创建项目、导入spring依赖
2、配置spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--配置user对象创建-->
<bean id="user" class="com.dao.userDao" abstract="true"></bean>
</beans>
3、测试代码编写
@Test
public void test(){
ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
userDaoImpl userDaoImpl=context.getBean("user", com.dao.userDaoImpl.class);
userDaoImpl.getUser();
}
二、IOC理论推导
1、userDao接口
2、userDaoImpl实现类,实现类可能会有多个
3、userService业务接口
4、userServicrImpl业务实现类
在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改代码,如果代码量大。修改一次成本很大。
使用了set注入后,程序不用在主动性,而是变成了被动的对象
public class mytest {
public static void main(String[] args) {
userService users=new userServicrImpl();
((userServicrImpl) users).setuserDao(new userDaoImpl());
users.getUser();
}
}
Ioc工程
第一步:创建spring的配置文件
id:唯一标识
class:创建对象类的全路径(包类路径)
<!--配置创建-->
<bean id="user" class="com.dao.userDaoImpl"></bean>
第二步:有service类和dao类,创建工厂类
class userFactory{
pub;ic static userDao getDao(){
String classValue=class.属性值 //xml解析
Class class=Class.forName(classValue) //通过反射创建对象
return (UserDao)class.newInstance()
}
}
Spring 提供IOC容器实现两种方式:(两个接口)
BeanFactory:IOC容器基本实现,是spring内部的使用
ApplicationContext:是BeanFactory的子接口,比其功能更加强大,常用
也就是我们彻底不用再程序中去改动代码了,要实现不同的操作,只需要在xml文件中进行修改,
IOC就是将对象有spring来创建、管理和装配。
三、spring配置说明
别名
<!--别名,添加了别名之后,可以使用别名获取到这个对象-->
<alias name="user" alias="userssss"></alias>
bean的配置
id:唯一标识
class:创建对象类的全路径(包类路径)
<!--配置创建-->
<bean id="user" class="com.dao.userDaoImpl"></bean>
import
import一般用于团队开发使用,可以将多个配置文件,导入合并为一个
四、依赖 注入
构造器注入
<bean id="hello1" class="com.app.Hello">
<constructor-arg index="0" value="arg1"/>
<constructor-arg index="1" value="2"/><!-- arg2 -->
<constructor-arg index="2" ref="world"/><!-- arg3 -->
</bean>
set注入
依赖注入:set注入,bean对象的创建依赖于容器,bean对象的所有属性由容器注入
使用property完成属性注入
name:类里面属性名称
value:向属性注入的值
<bean id="student" class="com.bean.Student">
<!--普通注入--><!-- bean注入用ref-->
<property name="name" value="莉莉"/>
<property name="adress" value="福建"/>
<!--数组注入-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
</array>
</property>
<!--list注入-->
<property name="hobbys">
<list>
<value>听歌</value>
<value>打代码</value>
</list>
</property>
<!--map注入-->
<property name="card">
<map>
<entry key="身份证" value="123"></entry>
<entry key="信用卡" value="456"></entry>
</map>
</property>
<!--set注入-->
<property name="games">
<set>
<value>斗地主</value>
<value>王者荣耀</value>
</set>
</property>
</bean>
student
public class Student {
String name;
String address;
String[] books;
List<String> hobbys;
Map<String,String> card;
Set<String> games;
}
测试
@Test
public void test2(){
ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
Student student= (Student) context.getBean("student");
System.out.println(student.toString());
}
其他方法注入
c命名空间和p命名空间
p命名空间注入可以直接注入属性的值
1、引入
xmlns:p="http://www.springframework.org/schema/p"
2、使用
p命名空间注入可以直接注入属性的值,相当于property
<bean id="student" class="com.bean.Student" p:name="莉莉" p:address="福建">
<!--普通注入--><!-- bean注入用ref
--<property name="name" value="莉莉"/>
--<property name="adress" value="福建"/>
-->
</bean>
1、导入
xmlns:c=”http://www.springframework.org/schema/c”
2、使用c命名空间并且是使用构造参数的索引作为属性来通过构造方法注入的bean定义
<!-- 传统的使用constructor-arg通过构造方法注入的bean定义 -->
<bean id="hello1" class="com.app.Hello">
<constructor-arg index="0" value="arg1"/>
<constructor-arg index="1" value="2"/><!-- arg2 -->
<constructor-arg index="2" ref="world"/><!-- arg3 -->
</bean>
<!-- 使用c命名空间并且是使用构造参数的索引作为属性来通过构造方法注入的bean定义 -->
<bean id="hello2" class="com.app.Hello" c:_0="c_arg1" c:_1="2" c:_2-ref="world"/>
bean的作用域
目前Spring Bean的作用域或者说范围主要有五种。
1、单例模式(spring默认)
<bean id="student" class="com.bean.Student" scope="singleton"></bean>
2、原型模式-prototype:每次从容器中get的时候,都会产生一个新对象!
3、其余的,只能在web开发中使用到
五、Bean自动装配
自动装配是spring 满足bean依赖一种方式!
-
spring 会在上下文中自动寻找,并自动给bean装配属性
在spring有三种装配属性
1、xml中显示的配置
2、在java中显示配置
3、隐射的自动装配bean
byName和byType
byname:会字段在容器上下文件中查找,和自己对象set方法后面相对应的beanid
<bean id="cat" class="com.bean.Cat"></bean>
<bean id="dog" class="com.bean.Dog"></bean>
<bean id="people" class="com.bean.People" autowire="byName">
</bean>
byType:会字段在容器上下文件中查找,和自己对象属性类型相同的beanid
<bean class="com.bean.Cat"></bean>
<bean class="com.bean.Dog"></bean>
<bean id="people" class="com.bean.People" autowire="byType">
</bean>
注意:
byname的时,需要保证所有的bean的id唯一,并且bean需要和自动注入的属性的set方法的值一致;
bytype的时,需要保证所有的bean的class唯一,并且bean需要和自动注入的属性类型一致;
注解实现自动装配
jdk1.5支持的注解,spring2.5就支持注解了!
使用须知:
public class People {
String name;
@Autowired
Dog dog;
@Autowired
Cat cat;
}
1、导入约束,context约束
2、配置注解的支持**<context:annotation-config/>**
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!--开启注解的支持-->
<context:annotation-config/>
<bean id="dog" class="com.bean.Dog"></bean>
<bean id="cat" class="com.bean.Cat"></bean>
<bean id="people" class="com.bean.People">
</bean>
</beans>
3、测试
public class test {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");
People people = context.getBean("people", People.class);
people.getDog().shout();
}
}
@Autowired
直接在属性上使用即可,也可以在set方式上使用!
使用Autowired我们可以不用编写set方法了,前提是你这个自动装配的属性在IOC(spring)容器中存在,且符合名字byname!
科普:
@Nullable:字段标记了这个注解,说明这个字段可以为null
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【Autowired】完成的时候,我们可以使用@Qualifier(value="XXX")去配置Autowired的使用,使用唯一的bean对象注入。
小结:
@Resource 和@Autowired的区别:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired 通过byType的方式实现,而且必须要求这个对象存在!
- @Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下就报错!
- 执行顺序不同:@AutoWired通过byType的方式实现
六、使用注解开发
在spring4之后,要使用注解开发,必须要求aop的包导入了
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.pojo"/>
<!--开启注解的支持-->
<context:annotation-config/>
<bean id="dog" class="com.bean.Dog" scope="prototype"></bean>
<bean id="cat" class="com.bean.Cat"></bean>
<bean id="people" class="com.bean.People">
<property name="name" value="楠楠"></property>
</bean>
</beans>
1、bean
@Component:组件,放在类上面,说明这个类被spring管理了,就是bean
2、属性如何注入
@Value("楠楠") //相当于<property name="name" value="楠楠"></property>
String name;
3、衍生的注解
@Component有几个衍生的注解,我们在web开发中,会按照mvc三层架构分层!
dao @Repository
@Repository
public class Dog {
String shout;
}
service @Service
controller @Controller
这四个注解的功能都是一样的,都是代表将某个类注解到spring中,bean!
4、自动装配置
@Autowired:自动装配通过类型名字
如果@Autowired不能尾牙自动装配上属性,则需要通过@Qualifier(value="XXX")
@Nullable:字段标记了这个注解,说明这个字段可以为null
@Resource:自动装配通过名字,类型
5、作用域
@Scope("singleton") 单例模式
@Scopr(" prototype") 原型模式
@Component
@Scope("prototype")
public class People {
@Value("hahaha")
String name;
@Autowired
Dog dog;
@Autowired
Cat cat;
}
小结:
xml与注解:
- xml更加万能,适用于任何场合,维护简单方便
- 注解不是自己类的话使用不了,维护相对复杂
xml与注解的最佳实践
- xml用来管理bean
- 注解只负责完成属性的注入
- 我们在使用的过程中,只需要注意一个问题:必须让注解生效,就要开启注解的支持
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.pojo"/>
<!--开启注解的支持-->
<context:annotation-config/>
七、使用java的方式配置spring
在这种java的配置方式,在spring boot方式中随处可见
javaconfig是spring的一个子项目,在spring4之后,它成为了一个新功能
user.class
@Component
public class User {
@Value("康康")
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
MyConfig.class
//这个也会被注册到spring容器,因为这个也是个组件Component
//@Configuration 代表这是一个配置类,和我们之前看的spring.xml一样
@Configuration
@ComponentScan("com.dao") //可以进行扫描
public class MyConfig {
//注册一个bean,就相当于我们之前写的bean标签,这个方法的名字,就是相当于bean标签中的id属性
//这个方法的返回值就相当于bean标签的class
@Bean
public User getUser(){
return new User();
}
}
测试:
public class Mytest {
public static void main(String[] args) {
//如果完全使用了配置方式去做我们可以通过ApplicationContext上下文来获取容器
ApplicationContext Context =new AnnotationConfigApplicationContext(MyConfig.class);
User get= (User) Context.getBean("getUser");
System.out.println(get.getName());
}
}
八、代理模式
为什么要学习代理模式,因为这个就是spring AOP的底层
代理模式的方式:
动态代理
静态代理
静态代理
角色分析:
- 抽象角色:一般会使用接口或抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
- 客户:访问代理对象的人!
操作步骤:
1、接口
public interface Rent {
public void rent();
}
2、真实角色
public class Host implements Rent{
public void rent() {
System.out.println("房东要出租房子");
}
}
3、代理角色
public class Proxy {
Host host;
public Proxy(Host host) {
seeHouse();
writehtong();
fare();
this.host = host;
}
public Proxy() {
}
public void rent(){
host.rent();
}
public void seeHouse(){
System.out.println("中介带你看房子");
}
public void fare(){
System.out.println("收中介费用");
}
public void writehtong(){
System.out.println("签合同");
}
}
4、客户端访问代理角色
public class Client {
public static void main(String[] args) {
Host host=new Host();
Proxy xy=new Proxy(host);
xy.rent();
}
}
代理模式的好处:
- 可以使真实角色的操作更加纯碎,不用去关注一些公共的业务
- 公共的就是交给代理角色!实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理!
缺点:
一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会低
加深理解
动态代理:
动态代理和静态代理的角色一样
动态代理的代理类是动态生成的,不是我们直接写好的
-
动态代理分为两大类:基于接口的动态代理,基于类的动态代理
基于接口---JDK动态代理(在这里使用)
基于类:cglib
java字节码实现:javasist
需要了解两个类:Proxy代理 InvocationHandler:调用处理程序
JDK动态代理
使用JDK动态代理需要使用:
Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
参数说明:
- ClassLoader loader: the class loader to define the proxy class,用于定义代理类的类加载器
- Class<?>[] interfaces: the list of interfaces for the proxy class,代理类的接口列表
- InvocationHandler h: to implement,由代理实例的调用处理程序实现的接口
出租的接口:
public interface Rent {
public void rent();
}
房东:
public class Host implements Rent {
public void rent() {
System.out.println("房东要出租房子");
}
}
代理
//会使用这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
Rent rent;
public void setRent(Rent rent) {
this.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);
seehouse();
fare();
return result;
}
public void seehouse(){
System.out.println("中介带去看房子");
}
public void fare(){
System.out.println("中介收取费用");
}
}
测试
public class Client {
public static void main(String[] args) {
//真实角色
Host host=new Host();
/*代理角色*/
ProxyInvocationHandler pih=new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象!
pih.setRent(host);
Rent proxy=(Rent) pih.getProxy();
proxy.rent();
}
}
动态代理的好处:
可以使真实角色的操作更加纯碎,不用去关注一些公共的业务
公共的就是交给代理角色!实现了业务的分工
公共业务发生扩展的时候,方便集中管理!
一个动态代理类代理的是一个接口,一般就是对应一类业务
九、AOP
什么是AOP
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP在Spring中的作用
提供声明式事务;允许用户自定义切面
以下名词需要了解下:
横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
目标(Target):被通知对象。
代理(Proxy):向目标对象应用通知之后创建的对象。
切入点(PointCut):切面通知 执行的 “地点”的定义。
连接点(JointPoint):与切入点匹配的执行点。
即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 .
在springAOP中,通过advice定义横切逻辑,spring中支持5中类型的advice:
前置通知、后置通知、环绕通知(方法前后)、异常抛出通知、引介通知(类中增加新的方法属性)
即AOP在不改变原有代码的情况下,去增加新的功能。
使用Spring实现aop
导入依赖(使用AOP织入需要导入依赖)
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
方式一:使用spring的接口
主要是spring aop接口实现
UserService
public interface UserService {
public void add();
public void delete();
public void find();
public void query();
}
UserServiceImpl
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("增加了一个用户");
}
public void delete() {
System.out.println("删除了一个用户");
}
public void find() {
System.out.println("找到了一个用户");
}
public void query() {
System.out.println("查询了一个用户");
}
}
springconfig.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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注册bean-->
<bean id="userService" class="com.service.UserServiceImpl"/>
<bean id="log" class="com.log.Log"/>
<bean id="afterlog" class="com.log.Afterlog"/>
<!--方式一:使用原生spring 接口-->
<!--配置aop:需要导入aop的约束-->
<aop:config>
<!--切入点 expression表达式,execution(要执行的位置!)-->
<aop:pointcut id="pointcut" expression="execution(* com.service.*.*(..))"/>
<!--分别将log 和afterlog切入到其中-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"></aop:advisor>
</aop:config>
</beans>
测试类
public class Mytest {
private static UserService userService;
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("springconfig.xml");
userService= (UserService) context.getBean("userService");
userService.add();
}
}
方式二:自定义类来实现aop
主要是切面定义
public class DiyPoinCut {
public void before(){
System.out.println("执行前");
}
public void after(){
System.out.println("执行后");
}
}
<!--方式二:自定义类-->
<bean id="diy" class="com.diy.DiyPoinCut"></bean>
<aop:config>
<!--自定义切面 ref要引用的类-->
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="point" expression="execution(* com.service.UserServiceImpl.*(..))"/>
<!--通知-->
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
测试不变
方式三:使用注解实现
@Aspect //标注这个类是一个切面
public class AnotPoint {
@Before("execution(* com.service.UserServiceImpl.*(..))")
public void Tbefore(){
System.out.println("执行前——---");
}
@After("execution(* com.service.UserServiceImpl.*(..))")
public void Tafter(){
System.out.println("执行后——---");
}
@Around("execution(* com.service.UserServiceImpl.*(..))")
public void Tter(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前");
pjp.proceed();
System.out.println("环绕后");
}
}
<bean id="anotPoint" class="com.diy.AnotPoint"></bean>
<!-- 开启注解支持! JDK(默认)-proxy-target-class="false" cglib-proxy-target-class="true"-->
<aop:aspectj-autoproxy proxy-target-class="false"/>
十、整合Mybatis
回忆Mybatis
1、导入相关jar包
junit、mybatis、mysql数据库、spring相关的、aop织入、mybatis-spring
2、编写配置文件
3、测试
注意:Maven:src/main/resources中xml文件不加载到classpath中
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.xls</include>
<include>**/*.xlsx</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
Mybatis-spring
1、编写数据源配置
2、sqlSessionFactory
3、sqlSessionTemplate
4、需要给接口加实现类
5、将自己写的实现类注入到spring中
6、测试使用即可
Mybatis.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">
<!--mybatis的主配置文件-->
<configuration>
<typeAliases>
<typeAlias type="com.dao.User" alias="User"></typeAlias>
</typeAliases>
<!--
<environments default="mysql">
<environment id="mysql">
<transactionManager type="jdbc"></transactionManager>
<dataSource type="POOLED">
<!–配置数据库的4个基本信息–>
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/myweb" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/mapper/UserMapper.xml"></mapper>
</mappers>-->
</configuration>
spring.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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- dataresource:使用spring的数据源替换mybatis的配置
我们这里属于spring 提供的jdbc:org.springframework.jdbc.datasource-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/myweb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!--绑定mybatis的配置文件-->
<property name="configLocation" value="classpath:Mybatis.xml"/>
<property name="mapperLocations" value="classpath:com/mapper/*.xml"/>
</bean>
<!-- SqlSessionTemplate:就是我们使用的sqlsession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能使用构造器注入sqlSessionFactory,因为它没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="userDao" class="com.dao.UserDaoImp">
<property name="sessionTemplate" ref="sqlSession"/>
</bean>
</beans>
接口实现UserDaoImp
public class UserDaoImp implements UserDao {
SqlSessionTemplate sessionTemplate;
public UserDaoImp() {
}
public void setSessionTemplate(SqlSessionTemplate sessionTemplate) {
this.sessionTemplate = sessionTemplate;
}
public List<User> findAll() {
UserDao userDao = (UserDao)this.sessionTemplate.getMapper(UserDao.class);
return userDao.findAll();
}
}
测试
@Test
public void Test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserDao userDao=context.getBean("userDao",UserDao.class);
for(User user:userDao.findAll()){
System.out.println(user);
}
}
十一、声明式事务
回顾事务
- 把一组业务当成一个业务来做,要么都成功,要么都失败
- 事务在项目开发中,十分重要,涉及到数据的一致性问题,不能马虎
- 确保完整性和一致性
事务的四大特性
原子性
事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
一致性
事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
隔离性
一个事务的执行不能被其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
持续性
也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- dataresource:使用spring的数据源替换mybatis的配置
我们这里属于spring 提供的jdbc:org.springframework.jdbc.datasource-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/myweb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<!--绑定mybatis的配置文件-->
<property name="configLocation" value="classpath:Mybatis.xml"/>
<property name="mapperLocations" value="classpath:com/mapper/*.xml"/>
</bean>
<!-- SqlSessionTemplate:就是我们使用的sqlsession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能使用构造器注入sqlSessionFactory,因为它没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="userDao" class="com.dao.UserDaoImp">
<property name="sessionTemplate" ref="sqlSession"/>
</bean>
<!--配置声明式事务---------------------------------------------------->
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource"/>
</bean>
<!--结合AOP实现事务的织入-->
<!--配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--配置事务的传播特性-->
<tx:attributes>
<tx:method name="add"/>
<tx:method name="delete"/>
<tx:method name="update"/>
<tx:method name="query"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
spring主要注解
@Autowired 自动按类型自动装配