Spring Study
1 What is Spring Framework?
Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
2002年,首次推出Spring Framework的雏形(interface 21)
Spring Framework的创始人 Rod Johnson,悉尼大学的音乐博士。
1.1 Spring的理念
理念:使现有的技术更加容易使用。
1.2 Spring Framework maven dependcy
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.9</version>
</dependency>
1.3 Spring优点
- Spring是一个开源的免费的框架(容器)!
- Spring是一个轻量级的、非入侵式的框架!(所谓非入侵式就是:引入这个框架并不会破坏原本的项目)
- 控制反转(IOC)、面向切面编程(AOP)
- 支持事务的处理
- 对框架整合的支持!
1.3 组成
1.4 总结
Sping本身就是一个大杂烩,整合了现有的技术框架!
Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!
1.5 拓展
现代化的Java开发!其实就是基于Spring的开发!
- Spring Boot:一个快速开发的脚手架(基于SpringBoot可以快速地开发单个微服务)
- Spring Cloud:基于SpringBoot实现
现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!
Spring发展太久带来弊端:配置十分繁琐
2 IOC理论
2.1 引入 (IOC的一个原型)
在以前的开发过程中:
- UserDao接口
- UesrDaoImpl实现类
- UserService业务接口
- UserServiceImpl业务实现类
在之前的开发中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改代码!如果程序的代码量很大,那么修改代码的成本非常昂贵。
我们可以使用setter()注入
等方法来消除程序的主动性。把程序的主动创建对象变成了被动的接受对象。
程序员不需要再去管理对象的创建了,大大降低了系统的耦合性,可以更加专注在业务的实现上!
2.2 简介
控制反转(IOC)是一种通过描述(XML或者注解)并通过第三方去生产或获取特定对象的方式。
在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection, DI)。
2.3 第一个Spring程序 HelloSpring
- 编写pojo
public class Hello { private String hello; public Hello() { } public Hello(String hello) { this.hello = hello; } public String getHello() { return hello; } public void setHello(String hello) { this.hello = hello; } @Override public String toString() { return "Hello{" + "hello='" + hello + '\'' + '}'; } }
- 配置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 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!--使用Spring来创建对象,在Spring这些都称为Bean 类型 变量名 = new 类型(); Hello hello = new Hello(); id = 变量名 class = new 的对象 property 相当于给对象中的属性设置一个值! --> <bean id="hello" class="com.jjj.pojo.Hello"> <property name="hello" value="testtt"/> </bean> </beans>
- 编写测试类
public class Mytest { @Test public void test(){ //获取Spring上下文对象 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //我们的对象现在都在Spring中管理了,我们要使用,直接去里面取出来就可以! Hello hello = (Hello) context.getBean("hello"); System.out.println(hello.toString()); } }
- 结果
通过一系列的操作,可以彻底不用在程序中改动代码,就实现不同的操作,只需要在xml配置文件中进行修改。
2.4 IOC创建对象的方式
- 默认:使用无参构造函数创建对象
- 有参构造函数
<!-- 1.参数下标赋值 --> <bean id="user" class="com.jjj.pojo.User"> <constructor-arg index="0" value="helloWorld"/> </bean> <!-- 2.通过参数类型 --> <bean id="user" class="com.jjj.pojo.User"> <constructor-arg type="java.lang.String" value="hello"/> </bean> <!-- 3.直接通过参数名称 --> <bean id="user" class="com.jjj.pojo.User"> <constructor-arg name="name" value="hellojjj"/> </bean>
- Spring的容器内的的所有实体类在注册过后,在配置文件加载的时候就被实体化!!
3 Spring配置
3.1 别名
<alias name="oldName" alias="newName"/>
如果添加了别名,可以通过别名来取到对象
5.2 Bean
<bean id="对象名(唯一标识符)" class="bean对象所对应的全限定名" [name="别名1","别名2"]>
5.3 import
一般用于团队开发,可以将多个配置文件,导入合并成一个。使用的时候只需要直接使用总的配置文件。
<import resource="地址">
4 依赖注入
4.1 构造器注入
前面已经提到
4.2 Set方式注入 【重要】
- 依赖:bean对象的创建依赖于容器。
- 注入:bean对象中的所有属性,由容器来注入。
<bean id="student" class="com.jjj.pojo.Student">
<!--第一种:普通类型注入-->
<property name="name" value="小明"/>
<!--第二种:Bean注入,ref-->
<property name="address" ref="address"/>
<!--第三种: 数组注入-->
<property name="books" >
<array>
<value>西游记</value>
<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="123456789123456789"/>
<entry key="电话卡" value="12345678901"/>
</map>
</property>
<!--第六种 set注入-->
<property name="game">
<set>
<value>LOL</value>
<value>王者荣耀</value>
</set>
</property>
<!--第七种 空值注入-->
<property name="wife">
<null></null>
</property>
<!--第八种 注入properties-->
<property name="info">
<props>
<prop key="学号">1912630135</prop>
<prop key="年级">大三</prop>
<prop key="性别">男</prop>
</props>
</property>
</bean>
4.3 拓展方式
我们可以使用p命名空间和c命名空间进行注入。只需要导入导入p/c命名空间约束。
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!--p命名空间注入,可以直接注入属性的值 property-->
<bean name="user" class="com.jjj.pojo.User" p:name="张三" p:age="18"/>
<!--c命名空间注入,通过构造器注入 construct-->
<bean name="user2" class="com.jjj.pojo.User" c:name="李四" c:age="18"/>
</beans>
5 Bean Scope
创建Bean的同时会确定一个作用域
<bean id="" class="" scope="作用域">
- singleton 单例模式 spring的默认机制 弊端:线程可能产生问题
- prototy 原例模式 每次从容器中get的时候,都会长生一个新的对象!弊端:浪费资源
- 剩下的request、session、application在web开发中遇到。
6 Bean的自动装配
自动装配是Spring满足Bean依赖的一种方式。
Spring会在上下文中自动寻找,并自动给Bean装配属性。
在Spring中有三种装配方式:
1.在xml中显式地配置
2.在java中显式地配置
3.隐式地自动装配Bean【重要】
6.2 测试
一个人可以有猫和狗
<bean id="cat" class="com.jjj.pojo.Cat"/>
<bean id="dog" class="com.jjj.pojo.Dog"/>
<bean id="people" class="com.jjj.pojo.People">
<property name="name" value="张三"/>
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
</bean>
6.1 byName自动装配
<bean id="people" class="com.jjj.pojo.People" autowire="byName">
<property name="name" value="张三"/>
</bean>
byName自动装配会在容器context中查找,查找和自己对象set方法后面的值同名的bean。
弊端:所有Bean的id必须唯一,并且这个bean需要和自动注入的属性的set方法的值一致。
6.2 byType自动装配
byType自动装配会在容器context中查找,查找和自己对象属性类型相同的bean。
弊端:所有Bean的class必须唯一,并且这个bean需要和自动注入的属性的类型一致。
7 使用注解实现自动装配
首先需要导入约束,然后配置注解的支持。
<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
</beans>
7.1 @Autowired
直接在属性上使用该注解!也可以在Setter方法上使用!
使用@Autowired我们可以不用编写Set方法,前提是这个自动装配的属性在IOC容器(xml文件)中存在。
如果显式定义了@Autowired的required属性值为false,说明这个对象可以为null,否者不允许空值。
如果@Autowired自动装配环境比较复杂,自动装配无法通过@Autowired完成的时候,我们可以使用@Qualifier(Value=“name”)去配置@Autowired的使用,指定一个唯一的bean对象注入!
8 使用注解开发
在Spring4之后,要使用注解开发,必须要保证aop的包导入;
使用注解需要导入context约束,和注解的支持。
8.1 bean
@Component
在类上使用该注解, 说明这个类就被Spring管理了,成为了bean。
8.2 属性的注入
@Value("")
8.3 衍生注解
@Component
有几个衍生注解,我们在web开放中,会按照mvc三层架构分层!
- dao
@Repository
- service
@Service
- controller
@Controller
这四个注解功能都是一样的,都是表示将这个类注册到Spring中,装配成bean。
8.4 作用域
@Scope("singleton")
8.5 xml和注解:
- xml更加万能,适用于任何场合!维护简单方便!
- 注解不是自己的类用不了,维护相对复杂。
- xml用来管理bean,注解只用来管理属性的注入。
- 在开发过程中,必须要开启注解支持,让注解生效。
<!--可以扫描特定的包--> <context:component-scan base-package="com.jjj"/>
9 使用Java的方式配置Spring
完全不适用Spring的xml,全程交给java来做。
JavaConfig是Spring的一个子项目,在Spring4之后,成为了一个核心功能。
//这个也会被Spring容器托管,注册到容器中,因为这个注解本身也是一个@Component,@Configuration代表这是一个配置类,就和beans.xml一样
1.配置类
@Configuration
public class MyConfig {
//注册一个Bean,就相当于一个bean标签,方法名就相当于id属性,返回值就相当于class属性;
@Bean
public User myUser(){
return new User();
}
}
2.测试类
@Test
public void test(){
//如果完全使用了配置类方式去做,就只能通过AnnotationConfigContext来获取容器,通过配置类的class对象加载。
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User myUser = (User) context.getBean("myUser");
System.out.println(myUser);
}
10 代理模式
有一个中介帮客户去完成复杂的事情。
10.1 静态代理
举例:
现实生活中租房,可以直接找房东租房,但是在找不到房东的时候就去找中介租房。因为中介有大量的房源,同时通过中介租房会产生很多附加的活动和条件。
角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,一般会有一些附属操作
- 客户:访问代理对象的人
代码:
- 接口
//租房 public interface Rent { public void rent(); }
- 真实角色
public class Host implements Rent { @Override public void rent() { System.out.println("房东出租房子"); } }
- 代理角色
public class Proxy implements Rent{ private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } @Override public void rent() { seeHouse(); host.rent(); fare(); } //看房 public void seeHouse(){ System.out.println("中介带客户看房"); } //收中介费 public void fare(){ System.out.println("收中介费,签合同"); } }
- 客户
public class Client { public static void main(String[] args) { System.out.println("直接找房东"); Host host = new Host(); host.rent(); System.out.println(); //通过中介租房 System.out.println("通过中介"); Proxy proxy = new Proxy(host); proxy.rent(); } }
代理模式的好处:
- 可以使真是角色的操作更加纯粹,不需要去关注公共业务
- 公共业务直接交给代理角色!实现了业务的分工!
- 公共业务发生拓展的失手,方便集中管理。
静态代理的缺点:一个真实角色就会产生一个代理角色,代码量会翻倍开发效率会变低。
运用:不改变原来代码增加新功能。
10.2 动态代理
动态代理的和静态代理角色一样。
动态代理的代理类是动态生成的,不是直接写好的。
动态代理分为两类:
- 基于接口的动态代理—JDK动态代理
- 基于类的动态代理—cglib
- java字节码实现—JAVAssist
11 AOP
AOP是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。
11.1 AOP在Spring中的作用
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与业务逻辑无关,但是需要关注的部分就是横切关注点,如日志、安全、缓存、事务等……
- 切面(ASPECT):横切关注点被模块化的特殊对象。即一个类
- 通知(Advice):切面必须要完成的工作。是类中的方法
- 目标(Target):被通知对象。
- 切入点(PointCut):切面通知 执行的"地点"的定义。
- 连接点(JointPoint):与切入点匹配的执行点。
11.2 使用Spring实现AOP
maven依赖:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
11.2.1 方式一 使用Spring的API接口
接口:
public interface UserService {
public void add();
public void delete();
public void update();
public void select();
}
接口的实现类:
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加用户");
}
@Override
public void delete() {
System.out.println("删除用户");
}
@Override
public void update() {
System.out.println("修改用户");
}
@Override
public void select() {
System.out.println("查询用户");
}
}
添加的功能:
public class Log implements MethodBeforeAdvice {
//method:要执行的目标对象的方法
//args:参数
//target:目标对象
@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 {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回结果为"+o);
}
}
applicaitonContext.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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="userService" class="com.jjj.service.UserServiceImpl"/>
<bean id="log" class="com.jjj.log.Log"/>
<bean id="afterLog" class="com.jjj.log.AfterLog"/>
<!--方式一:使用原生Spring API接口-->
<!--配置aop:需要导入aop的约束-->
<aop:config>
<!--需要一个切入点:expression(要执行的位置)表达式-->
<aop:pointcut id="pointcut" expression="execution(* com.jjj.service.UserServiceImpl.*(..))"/>
<!--执行环绕增加!-->
<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>
</beans>
测试类:
public class MyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理的是接口
UserService userService = (UserService) context.getBean("userService", UserService.class);
userService.add();
}
}
结果:
11.2.2 自定义类来实现AOP(主要是切面定义)
自定义类:
public class DiyPointCut {
public void before(){
System.out.println("===============方法执行前================");
}
public void after(){
System.out.println("===============方法执行后================");
}
}
xml:
<bean id="diy" class="com.jjj.diy.DiyPointCut"/>
<aop:config>
<aop:aspect ref="diy">
<!--切入点-->
<aop:pointcut id="pointcut" expression="execution(* com.jjj.service.UserServiceImpl.*(..))"/>
<!--通知-->
<aop:before method="after" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
测试类不变
11.2.3 使用注解实现
//方式三:使用注解方式实现AOP
@Component
@Aspect//标注这个类是一个切面
public class AnnotationPointCut {
@Before("execution(* com.jjj.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("=============before===========");
}
@After("execution(* com.jjj.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("=============after===========");
}
@Around("execution(* com.jjj.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
//执行方法
Object proceed = jp.proceed();
System.out.println("环绕后");
}
}
测试类和xml不变。
12 整合Mybatis
12.1 导入相关jar包
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.8</version>
</dependency>
<!--Spring操作数据库的话,还需要一个Spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
</dependencies>
12.2 编写编写配置文件文件
编写mybatis配置文件
12.3 mybatis-spring
- 编写sqlSessionFactory
- sqlSessionTemplate
- 需要给接口加实现类
- 将自己写的实现类交给spring托管
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!--DataSource:使用Spring的数据源替换Mybatis的配置
使用Spring提供的JDBC-->
<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_study"/>
<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"/>
<property name="mapperLocations" value="classpath:com/jjj/dao/*Mapper.xml"/>
</bean>
<!--SqlSessionTemplate:就是我们使用的sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能使用构造器注入sqlSessionFactory,因为它没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
</beans>
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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<import resource="spring-dao.xml"/>
<bean id="userMapper" class="com.jjj.dao.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
</bean>
</beans>
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>
<package name="com.jjj.pojo"/>
</typeAliases>
</configuration>
13 事务
13.1 什么是事务
- 把一组业务当成一个业务来做,要么都成功,要么都失败。
- 确保完整性和一致性。
为什么需要事务?如果不配置事务,可能存在数据提交不一致的情况!
如果不在Spring中配置生命式事务,我们就需要在项目中手动添加。
13.2 ACID原则
- 原子性
- 一致性:要么都成功、要么都失败
- 隔离性
- 持久性
13.3 spring中地事务管理
13.3.1 声明式事务
<!--结合Aop实现事务的织入-->
<!--配置事务通知-->
<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="query" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.jjj.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
如果不在Spring中配置生命式事务,我们就需要在项目中手动添加。
13.2 ACID原则
- 原子性
- 一致性:要么都成功、要么都失败
- 隔离性
- 持久性
13.3 spring中地事务管理
13.3.1 声明式事务
<!--结合Aop实现事务的织入-->
<!--配置事务通知-->
<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="query" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.jjj.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>