Spring简要介绍: 一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。
- 优点:
- Spring是一个开源免费的框架,容器.
- Spring是一个轻量级的框架,非侵入式的.
- 控制反转IoC,面向切面Aop
- 对事物的支持,对框架的支持
- 组成:
- 核心容器(Spring Core)
核心容器提供Spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。
- 应用上下文(Spring Context)
Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能。
- Spring面向切面编程(Spring AOP)
通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring框架中。所以,可以很容易地使 Spring框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
- JDBC和DAO模块(Spring DAO)
JDBC、DAO的抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息。异常层次结构简化了错误处理,并且极大的降低了需要编写的代码数量,比如打开和关闭链接。
- 对象实体映射(Spring ORM)
Spring框架插入了若干个ORM框架,从而提供了ORM对象的关系工具,其中包括了Hibernate、JDO和 IBatis SQL Map等,所有这些都遵从Spring的通用事物和DAO异常层次结构。
- Web模块(Spring Web)
Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文。所以Spring框架支持与Struts集成,web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
- MVC模块(Spring Web MVC)
MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。MVC容纳了大量视图技术,其中包括JSP、POI等,模型来有JavaBean来构成,存放于m当中,而视图是一个街口,负责实现模型,控制器表示逻辑代码,由c的事情。Spring框架的功能可以用在任何J2EE服务器当中,大多数功能也适用于不受管理的环境。Spring的核心要点就是支持不绑定到特定J2EE服务的可重用业务和数据的访问的对象,毫无疑问这样的对象可以在不同的J2EE环境,独立应用程序和测试环境之间重用。
- Spring Boot: 构建
- Spring Cloud:协调
- Spring Cloud Data Flow: 连接
IOC
实例
- UserDao接口
// interface: UserDao
package dao;
public interface UserDao {
void getUser();
}
- UserDaoImpl实现类
// 针对不同的需求,设计实现了多个该接口的实现类
// implements01: UserDaoImpl
package dao;
public class UserDaoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("get the data from user");
}
}
// implements02: UserDaoMysqlImpl
package dao;
public class UserDaoMysqlImpl implements UserDao {
@Override
public void getUser() {
System.out.println("Mysql: get the data from user");
}
}
// implements03:UserDaoOracleImpl
package dao;
public class UserDaoOracleImpl implements UserDao {
@Override
public void getUser() {
System.out.println("Oracle: get the data from user");
}
}
- UserService业务接口
package service;
import dao.UserDao;
public interface UserService {
// 满足不同需求
void setUserDao(UserDao userDao);
void getUser();
}
- UserServiceImpl业务实现类
package service;
import dao.UserDao;
public class UserServiceImpl implements UserService{
private UserDao userDao;
// 在业务层,根据不同需求,返回实现满足不同需求的服务
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void getUser() {
userDao.getUser();
}
}
- Test
import dao.UserDaoImpl;
import dao.UserDaoMysqlImpl;
import dao.UserDaoOracleImpl;
import service.UserService;
import service.UserServiceImpl;
public class MyTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
userService.setUserDao(new UserDaoImpl());
userService.getUser();
userService.setUserDao(new UserDaoMysqlImpl());
userService.getUser();
userService.setUserDao(new UserDaoOracleImpl());
userService.getUser();
}
}
- 将主动权交给用户
HelloSpring
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean就是java对象 , 由Spring创建和管理-->
<!-- id: 变量名 -->
<bean id="hello" class="pojo.Hello">
<property name="str" value="Spring"/>
</bean>
</beans>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Hello;
public class Mytest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 获取到由spring创建的对象
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.toString());
}
}
实例改进
- 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean就是java对象 , 由Spring创建和管理-->
<bean id="mysqlImpl" class="dao.UserDaoMysqlImpl"/>
<bean id="oracleImpl" class="dao.UserDaoOracleImpl"/>
<bean id="userServiceImpl" class="service.UserServiceImpl">
<!-- ref: 应用spring容器中创建好的对象 -->
<!-- value:基本数据类型 -->
<property name="userDao" ref="oracleImpl"/>
</bean>
</beans>
- Test
import dao.UserDaoImpl;
import dao.UserDaoMysqlImpl;
import dao.UserDaoOracleImpl;
import javafx.application.Application;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService;
import service.UserServiceImpl;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
UserServiceImpl userService = (UserServiceImpl) context.getBean("userServiceImpl");
userService.getUser();
}
}
IOC创建对象的方式
package pojo;
public class User {
private String name;
public User() {
System.out.println("调用了无参构造方法");
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("调用了set方法");
this.name = name;
}
public void show() {
System.out.println("name = " + name);
}
}
- 下标
<bean id="user" class="pojo.User">
<constructor-arg index="0" value="zcs"/>
</bean>
- 通过类型创建
<bean id="user" class="pojo.User">
<constructor-arg type="java.lang.String" value="zcs"/>
</bean>
- 通过参数名
<bean id="user" class="pojo.User">
<constructor-arg name="name" value="zcs"/>
</bean>
- 结论:在配置文件加载的时候。其中管理的对象都已经初始化了!
配置
- Alias: 别名
<alias name="user" alias="userNew>
- Bean
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
- import
<import resource="{path}/beans.xml"/>
依赖注入
构造器注入
依赖:bean对象的创建依赖
注入:bean中所有属性,由容器注入
- array
<property name="books">
<array>
<value>西游记</value>
<value>红楼梦</value>
<value>水浒传</value>
</array>
</property>
- list
<property name="hobbys">
<list>
<value>听歌</value>
<value>看电影</value>
<value>爬山</value>
</list>
</property>
- map
<property name="card">
<map>
<entry key="中国邮政" value="456456456465456"/>
<entry key="建设" value="1456682255511"/>
</map>
</property>
- set
<property name="games">
<set>
<value>LOL</value>
<value>BOB</value>
<value>COC</value>
</set>
</property>
- 空指针
<property name="wife"><null/></property>
- properties
<property name="info">
<props>
<prop key="学号">20190604</prop>
<prop key="性别">男</prop>
<prop key="姓名">小明</prop>
</props>
</property>
- P命名空间注入:需要在头文件中加入约束文件
导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<!-- 直接通过注入属性的值 -->
<bean id="user" class="pojo.User" p:name="zcs" p:age="21"/>
- C命名空间注入:
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<!--C(构造: Constructor)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="pojo.User" c:name="zcs" p:age="21"/>
Bean作用域
-
Bean:在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,bean就是由IoC容器初始化、装配及管理的对象
-
singleton:默认以单例模式存在
当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置:
<bean id="serviceImpl class="service.serviceImpl" scope="singleton">
- prototype:原型模式,每次从容器中get的时候,都会产生一个新对象
<bean id="serviceImpl class="service.serviceImpl" scope="prototype"> - request、session、application只能在web开发中使用
自动装配
-
spring满足bean依赖的一种方式
-
spring会在上下文中自动寻找,并自动给bean装配属性
-
三种装配方式:
- xml
- java
- 隐式的自动装配
byName:自动在容器上下文查找,和自己对象set方法后面的值对应的beanid,需保证所有bean的id唯一,并且和这个bean需要自动注入的属性的set方法一致
byType:和自己对象属性类型相同的beanid,需保证所有bean的class唯一,并且和这个bean需要自动注入的属性的类型一致
- 使用注解实现自动装配
<?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">
<context:annotation-config/>
</beans>
@Autowired:
- 直接在属性上使用即可,也可以在set方式中使用
- 使用Autowired 可以不用编写Set方法,前提是你这个自动装配的属性在IOC容器中存在,且符合名字byName
@Nullable: 此字段可以为空
public @interface Autowired {
boolean required() default true;
}
@Autowired(required = false)
说明这个对象可以为空,否则不允许为空
@Qualifier:指定一个唯一的bean对象注入
@Qualifier(value="xxx")
@Resource:如有指定的name属性,先按该属性进行byName方式查找装配;
其次再进行默认的byName方式进行装配;
如果以上都不成功,则按byType的方式自动装配。
使用注解开发
- 自动装配
- 属性注入
@Value("zcs")
public void setName(String name) {
this.name = name;
}
- 衍生注解:功能一样,将某个类注册到Spring容器中装配
@Component 有几个衍生注解,web开发中,采用MVC三层架构
- dao @Repsitory
- service @Service
- controller @Controller
- 作用域:@Scope
JavaConfig实现配置
package pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("zcs")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
- Config
package config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import pojo.User;
@ComponentScan("pojo")
@Configuration
public class ZcsConfig {
// 注册一个Bean,相当于一个Bean标签
// 方法名相当于id
@Bean
public User getUser() {
return new User();
}
}
- Test
import config.ZcsConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import pojo.User;
public class MyTest {
public static void main(String[] args) {
// 完全使用配置内方式,通过AnnotationConfigApplicationContext获取配置类的class对象加载
ApplicationContext context = new AnnotationConfigApplicationContext(ZcsConfig.class);
User user = (User) context.getBean("getUser");
System.out.println(user.getName());
}
}
代理模式
分类:静态代理、动态代理
- 静态代理
// 要实现的Service
public interface Rent {
public void rent();
}
public class Host implements Rent{
public void rent() {
System.out.println("apply Service");
}
}
// Proxy
public class Proxy implements Rent {
private Host host;
public Proxy() { }
public Proxy(Host host) {
this.host = host;
}
public void additionService() {
continue;
}
}
- 动态代理
动态代理的代理类是动态生成的
-
基于接口的动态代理
JDK动态代理 -
基于类的动态代理
cglib、javasist\
JDK的动态代理:InvocationHandler、 Proxy
InvocationHandler:是一个有代理实例的调用处理程序实现的接口,每一个代理实例都有一个关联的调用处理程序\
Proxy:提供了创建动态代理类和实例的静态方法\
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), service.getClass().getInterfaces(), this);
}
public class Host implements Service {
public void service() {
System.out.println("apply service");
}
}
// 动态代理类
public class ProxyInvocationHandler implements InvocationHandler {
private Service service;
public void setService(Service service) {
this.service = service;
}
//生成代理类,重点是第二个参数,获取要代理的抽象角色
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), service.getClass().getInterfaces(), this);
}
// proxy : 代理类 method : 代理类的调用处理程序的方法对象.
// 处理代理实例上的方法调用并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
additionService();
//核心:本质利用反射实现!
Object result = method.invoke(service, args);
return result;
}
//看房
public void additionService(){
System.out.println("addition Service");
}
}
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理实例的调用处理程序
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setService(service); //将真实角色放置进去!
Service proxy = (Service)pih.getProxy(); //动态生成对应的代理类!
proxy.service();
}
}
通用代理实现类
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
// proxy : 代理类
// method : 代理类的调用处理程序的方法对象.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
public void log(String methodName) {
System.out.println("执行了"+methodName+"方法");
}
}
Test
public class Test {
public static void main(String[] args) {
//真实对象
UserServiceImpl userService = new UserServiceImpl();
//代理对象的调用处理程序
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService); //设置要代理的对象
UserService proxy = (UserService)pih.getProxy(); //动态生成代理类!
proxy.delete();
}
}
动态代理好处:
-
可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
-
公共的业务由代理来完成 . 实现了业务的分工 ,
-
公共业务发生扩展时变得更加集中和方便 .
-
一个动态代理 , 一般代理某一类业务
-
一个动态代理可以代理多个类,代理的是接口!
AOP
方式一:通过Spring API 实现
- 设置业务接口
public interface UserService {
public void service();
}
- 设计业务实现类
public class UserServiceImpl implements UserService {
System.out.println("service for user");
}
- 两个增强类:前置和后置
public class Log implements MethodBeforeAdvice {
//method : 要执行的目标对象的方法
//objects : 被调用的方法的参数
//Object : 目标对象
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被执行了");
}
}
public class AfterLog implements AfterReturningAdvice {
//returnValue 返回值
//method被调用的方法
//args 被调用的方法的对象的参数
//target 被调用的目标对象
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了" + target.getClass().getName()
+"的"+method.getName()+"方法,"
+"返回值:"+returnValue);
}
}
- 配置文件
<?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="service.UserServiceImpl"/>
<bean id="log" class="log.Log"/>
<bean id="afterLog" class="log.AfterLog"/>
<!--aop的配置-->
<aop:config>
<!--切入点 expression:表达式匹配要执行的方法-->
<aop:pointcut id="pointcut" expression="execution(* service.UserServiceImpl.*(..))"/>
<!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
- Test
public class MyTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
UserService userService = (UserService) context.getBean("userService");
userService.service();
}
}
- 输出结果
service.UserServiceImpl的service方法被执行了
service for user
执行了service.UserServiceImpl的service方法,返回值:null
Spring的Aop就是将公共的业务 (日志 , 安全等) 和领域业务结合起来 , 当执行领域业务时 , 将会把公共业务加进来 . 实现公共业务的重复利用 . 领域业务更纯粹 , 程序猿专注领域业务 , 其本质还是动态代理 .
方式二:自定义类实现AOP
- 定义切入类
public class DiyPointcut {
public void before(){
System.out.println("---------方法执行前---------");
}
public void after(){
System.out.println("---------方法执行后---------");
}
}
- 配置文件
<!--第二种方式自定义实现-->
<!--注册bean-->
<bean id="diy" class="com.kuang.config.DiyPointcut"/>
<!--aop的配置-->
<aop:config>
<!--第二种方式:使用AOP的标签实现-->
<aop:aspect ref="diy">
<aop:pointcut id="diyPonitcut" expression="execution(* service.UserServiceImpl.*(..))"/>
<aop:before pointcut-ref="diyPonitcut" method="before"/>
<aop:after pointcut-ref="diyPonitcut" method="after"/>
</aop:aspect>
</aop:config>
- Test
public class MyTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
}
方式三:使用注解实现
- 编写注解实现的增强类
package com.kuang.config;
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 AnnotationPointcut {
@Before("execution(* service.UserServiceImpl.*(..))")
public void before() {
System.out.println("---------方法执行前---------");
}
@After("execution(* service.UserServiceImpl.*(..))")
public void after() {
System.out.println("---------方法执行后---------");
}
@Around("execution(* service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
System.out.println("签名:"+jp.getSignature());
//执行目标方法proceed
Object proceed = jp.proceed();
System.out.println("环绕后");
System.out.println(proceed);
}
}
- 配置文件
<!--第三种方式:注解实现-->
<bean id="annotationPointcut" class="com.kuang.config.AnnotationPointcut"/>
<aop:aspectj-autoproxy/>
通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring 在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了
<aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。
Spring整合Mybatis
- spring整合数据源、mybatis
<?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 id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useSSL=true&useUnicode=true&characterEncoding=utf8&useSSL=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 整合mybatis sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:Mapper/*.xml"/>
</bean>
<!-- 通过构造器自动创建sqlSessionFactory对象 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
</beans>
- applicationContext
<?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">
<import resource="classpath:spring-dao.xml"/>
<bean id="userMapper" class="Mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
</bean>
</beans>
- SQLSessionTemplate、实现类
package Mapper;
import org.mybatis.spring.SqlSessionTemplate;
import pojo.User;
import java.util.List;
public class UserMapperImpl implements UserMapper{
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List<User> selectUser() {
return sqlSession.getMapper(UserMapper.class).selectUser();
}
}
spring中的事务管理:声明式事务、编程式事务
编程式事务管理:
- 将事务管理代码嵌入到业务方法中来控制事务的提交和回滚
- 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码
声明式事务管理:
-
将事务管理代码从业务方法中分离出来,以声明的方式实现事务管理
-
将事务管理作为横切关注点通过AOP方法模块化
-
注册事务
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
- 配置事务的通知
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--配置哪些方法使用什么样的事务,配置事务的传播特性-->
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="search*" propagation="REQUIRED"/>
<tx:method name="get" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
- 配置AOP
<!--配置aop织入事务-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>