MIKU MOE

SSM_Spring_代理_AOP_整合

SSM_Spring


 

10. 代理模式

1. 静态代理

代理模式的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务

  • 公共也就就交给代理角色!实现了业务的分工!(耦合性降低)

  • 公共业务发生扩展的时候,方便集中管理!

缺点:

  • 一个真实角色就会产生一个代理角色,代码量会翻倍开发效率会变低

案例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();
             rent();
             contract();
             fare();
         }
         //看房
         public void seeHouse(){ System.out.println("看房"); }
         //合同
         public void contract(){ System.out.println("合同"); }
         //收费
         public void fare(){ System.out.println("收费"); }
     }
    复制代码

     

  • 客户【客户】∶访问代理对象的人!

    复制代码
     public class Client {
         public static void main(String[] args) {
             //房东要租房子
             Host host = new Host();
             //代理,代理附带操作
             Proxy proxy = new Proxy();
             //客户不需要面对房东,直接找中介
             proxy.rent();
         }
     }
    复制代码

     

案例2:

123

抽象方法

 
/*抽象方法*/
 public interface UserService {
     public void add();
     public void delete();
     public void update();
     public void query();
 }

 

真实对象 -- 实现类

复制代码
 /*实现类 - 真实对象*/
 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 query() { System.out.println("查"); }
     //改动原有的业务代码,在公司中是大忌!
 }
复制代码

 

代理对象 -- 增加日志功能

复制代码
 /*代理角色*/
 public class UserServiceProxy implements UserService{
     UserServiceImpl userService;
     public void setUserService(UserServiceImpl userService) {
         this.userService = userService; }
     @Override
     public void add() {
         log("add");
         userService.add();
     }
 ​
     @Override
     public void delete() {
         log("delete");
         userService.delete();
     }
 ​
     @Override
     public void update() {
         log("update");
         userService.update();
     }
 ​
     @Override
     public void query() {
         log("query");
         userService.query();
     }
     //增加日志功能
     public void log(String msg) { System.out.println("-- 使用了"+msg+"方法!"); }
 }
复制代码

 

测试

 public class Client {
     public static void main(String[] args) {
         UserServiceImpl userService = new UserServiceImpl();
         UserServiceProxy Proxy = new UserServiceProxy();
         Proxy.setUserService(userService);
         Proxy.add();
     }
 }

 

2. 动态代理

  • 动态代理和静态代理角色一样

  • 动态代理的代理类是动态生成的,不是我们直接写好的!

  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理。

    • 基于接口---JDK动态代理【我们在这里使用】

    • 基于类: cglib

    • java字节码实现: javasist

需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序

动态代理的好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共的业务

  • 公共也就就交给代理角色!实现了业务的分工!

  • 公共业务发生扩展的时候,方便集中管理!

  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务。

  • 一个动态代理类可以代理多个类,只要是实现了同一个接口即可!

案例1改进:

接口和实现类不需要改变

复制代码
 /*使用这个类,自动生成代理类*/
 public class ProxyInvocationHandler implements InvocationHandler {
     //被代理的接口
     private Rent rent;
     public void setRent(Rent rent) { this.rent = rent; }
     //生成得到的代理类
     public  Object getProxy(){
         return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
     }
     //处理代理实例,并返回结果
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         Object result = method.invoke(rent, args);
         return result;
     }
 }
复制代码

 

测试

复制代码
 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动态生成的
         proxy.rent();
     }
 }
复制代码

 

案例2改进:

复制代码
 /*使用这个类,自动生成代理类*/
 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);
     }
     //处理代理实例,并返回结果
     @Override
     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 msg) { System.out.println("-- 使用了"+msg+"方法!"); }
 }
复制代码

 

测试

复制代码
 public class Client {
     public static void main(String[] args) {
         //真实角色
         UserServiceImpl userService = new UserServiceImpl();
         //代理角色 : 当前无
         ProxyInvocationHandler pih = new ProxyInvocationHandler();
         //通过调用程序处理角色来处理我们要调用的接口对象
         pih.setTarget(userService);
         UserService proxy = (UserService) pih.getProxy();//proxy动态生成的
         proxy.delete();
     }
 }
复制代码

 

模板

复制代码
 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);
     }
     //处理代理实例,并返回结果
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         Object result = method.invoke(target, args);
         return result;
     }
     //只需要修改target即可
 }
复制代码

 


 

11. AOP

AOP (Aspect Oriented Programming)意为 : 面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

123

 

1. Aop在Spring中的作用

提供声明式事务;允许用户自定义切面

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等....

  • 切面(ASPECT)∶横切关注点被模块化的特殊对象。即,它是一个类。

  • 通知(Advice) : 切面必须要完成的工作。即,它是类中的一个方法。

  • 目标(Target) : 被通知对象。

  • 代理(Proxy)∶向目标对象应用通知之后创建的对象。

  • 切入点(PointCut) : 切面通知执行的“地点"的定义。

  • 连接点(JointPoint) : 与切入点匹配的执行点。

23

使用Spring实现Aop导包

 
<dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>aspectjweaver</artifactId>
     <version>1.9.4</version>
 </dependency>

 

方式一 : 使用Spring的API接口【主要SpringAPI接口实现】

方式二︰自定义来实现AOP【主要是切面定义】

方式三 : 使用注解实现AOP

方式1: 使用Spring的API接口

1

复制代码
 package com.study.log;
 import org.springframework.aop.MethodBeforeAdvice;
 import java.lang.reflect.Method;
 public class Log implements MethodBeforeAdvice {
     //method :要执行的目标对象的方法
     //args :参数
     //target: 日标对象
     public void before(Method method,Object[] args,Object target)throws Throwable{
         System.out.println(target.getClass().getName()+method.getName()+"被执行");
 ​
     }
 }
复制代码

 

2

 public class AfterLog implements AfterReturningAdvice {
     //returnValue:返回值
     public void afterReturning(Object returnValue,Method method,Object[] args,Object target)throws Throwable {
         System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnvalue);
     }
 }

 

注册到Spring中 applicationContext.xml

复制代码
 <!--方式一:使用原生Spring API接口-->
 <?xml version="1.0" encoding="UTF8"?>
 <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">
     <!--注册-->
     <bean id="userService" class="com.study.service.UserServiceImpl"/>
     <bean id="1og" class="com.study.log.Log"/>
     <bean id="afterLog" class="com.study.log.AfterLog"/>
      
     <!--配置aop,需要导入aop约束-->
     <aop:config>
         <!--切入点: expression:表达式,execution(要执行的位置!* * * * *)-->
         <aop:pointcut id="pointcut" expression="execution(* com.study.service.UserServiceImpl.*(..)"/>
         <!--执行环绕增加!-->
         <aop:advisor advice-ref="log" pointcut-ref="pointcut" />
         <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut" />
     </aop:config>
 </beans>
复制代码

 

测试

 public class MyTest {
     public static void main(String[] args) {
         ApplicationContext context = new classPathXmlApplicationContext("applicationContext.xml");//动态代理代理的是接口
         UserService userService = (Userservice) context.getBean("userService");
         userService.add();
     }
 }

 

方式2: 自定义类

自定义类

 public clasd DiyPointcut {
     public void before(){
         System.out.println( "========方法执行前=========");
     }
     public void after(){
         System.out.println( "========方法执行后=========");
     }
 }

 

注册

复制代码
 <?xml version="1.0" encoding="UTF8"?>
 <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">
     <!--注册-->
     <bean id="userService" class="com.study.service.UserServiceImpl"/>
     <bean id="1og" class="com.study.log.Log"/>
     <bean id="afterLog" class="com.study.log.AfterLog"/>
     
     <bean id="diy" class="com.study.diy.DiyPointcut"/>
     
     <aop:config>
         <!--自定义切面,ref要引用的类-->
         <aop:aspect ref="diy">
             <!--切入点-->
             <aop:pointcut id="point" expression="execution(* com.study.service.UserServicempl.*(..))"/>
             <!--通知-->
             <aop:before method="before" pointcut-ref="point"/>
             <aop:after method="after" pointcut-ref="point"/>
         </aop:aspect>
     </aop:config>
 </beans>
复制代码

 

方式3: 使用注解实现

复制代码
 @Aspect //标注这个类是一个切面
 public class AnnotationPointCut {
     //切入点 -- 找到类的所有方法(Impl.*),无论多少参数(..)
     @Before("execution(* com.study.service.userServiceImpl.*(..))")
     public void before(){
         System.out.println( "=====方法执行前======");
     }
     @After("execution(* com.study.service.userServiceImpl.*(..))")
     public void after(){
         System.out.println( "=====方法执行后======");
     }
     //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
     @Around("execution(* com.study.service.UserServiceImpl.*(..))")
     public void around(ProceedingJoinPoint jp) throws Throwable {
         System.out.print1n("环绕前");
         //jp.getSignature();//获得签名void com.study...UserService.具体执行的方法
         //执行方法
         Object proceed = jp.proceed();
         System.out.print1n("环绕后");
     }
 }
复制代码

 

配置

复制代码
 <!--方式三-->
 <bean id="annotationPointCut" class="com.kuang.diy.AnnotationPointCut"/>
 <!--
 ======开启注解支持======
 属性: proxy-target-class="false" 
 flase(默认) : 使用JDK
 true : cglib
 -->
 <aop:aspectj-autoproxy/>
复制代码

 

12. 整合MyBatis

步骤:

  1. 导入相关jar包

    • junito

    • mybatis

    • mysql数据库

    • spring相关的

    • aop织入

    • mybatis-spring 【new】

    复制代码
     <?xml version="1.0" encoding="UTF-8"?>
     <project xmlns="http://maven.apache.org/POM/4.0.0"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
         <parent>
             <artifactId>Spring1</artifactId>
             <groupId>org.example</groupId>
             <version>1.0-SNAPSHOT</version>
         </parent>
         <modelVersion>4.0.0</modelVersion><artifactId>spring_mybatis</artifactId><properties>
             <maven.compiler.source>8</maven.compiler.source>
             <maven.compiler.target>8</maven.compiler.target>
         </properties><dependencies>
             <!--Junit-->
             <dependency>
                 <groupId>junit</groupId>
                 <artifactId>junit</artifactId>
                 <version>4.12</version>
             </dependency>
             <!--MySQL-->
             <dependency>
                 <groupId>mysql</groupId>
                 <artifactId>mysql-connector-java</artifactId>
                 <version>5.1.48</version>
             </dependency>
             <!--MyBatis-->
             <dependency>
                 <groupId>org.mybatis</groupId>
                 <artifactId>mybatis</artifactId>
                 <version>3.5.7</version>
             </dependency>
             <!--spring-web-mvc-->
             <dependency>
                 <groupId>org.springframework</groupId>
                 <artifactId>spring-webmvc</artifactId>
                 <version>5.3.9</version>
             </dependency>
             <!--spring-jdbc-->
             <dependency>
                 <groupId>org.springframework</groupId>
                 <artifactId>spring-jdbc</artifactId>
                 <version>5.3.9</version>
             </dependency>
             <!--aspectjweaver-->
             <dependency>
                 <groupId>org.aspectj</groupId>
                 <artifactId>aspectjweaver</artifactId>
                 <version>1.9.7</version>
             </dependency>
             <!--mybatis-spring-->
             <dependency>
                 <groupId>org.mybatis</groupId>
                 <artifactId>mybatis-spring</artifactId>
                 <version>2.0.6</version>
             </dependency><dependency>
                 <groupId>org.projectlombok</groupId>
                 <artifactId>lombok</artifactId>
                 <version>1.18.20</version>
             </dependency>
         </dependencies><build>
             <resources>
                 <resource>
                     <directory>src/main/resources</directory>
                     <includes>
                         <include>**/*.properties</include>
                         <include>**/*.xml</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></project>
    复制代码

     

  2. 编写配置文件

  3. 测试

1. 回顾MyBatis

编写实体类 -- 使用的是MyBatis学习时建的表User

 @Data
 public class User {
     private int id;
     private String name;
     private String pwd;
 }

 

编写核心配置文件

复制代码
 <?xml version="1.0" encoding="UTF8" ?>
 <!DOCTYPE configuration
         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><typeAliases>
         <typeAlias type="com.study.pojo.User" alias="User"/>
     </typeAliases><environments default="development">
         <environment id="development">
             <transactionManager type="JDBC"/>
             <dataSource type="POOLED">
                 <property name="driver" value="com.mysql.jdbc.Driver"/>
                 <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                 <property name="username" value="root"/>
                 <property name="password" value="root"/>
             </dataSource>
         </environment>
     </environments><mappers>
         <mapper class="com.study.mapper.UserMapper"/>
     </mappers></configuration>
复制代码

 

编写接口

 public interface UserMapper {
     public List<User> selectUser();
 }

 

编写Mapper.xml

复制代码
 <?xml version="1.0" encoding="UTF8" ?>
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.study.mapper.UserMapper"><select id="selectUser" resultType="User">
         select * from mybatis.user;
     </select></mapper>
复制代码

 

测试

复制代码
 public class MyTest {
     public static void main(String[] args) throws IOException {
         String resources = "mybatis-config.xml";
         InputStream in = Resources.getResourceAsStream(resources);
         SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
         SqlSession sqlSession = sessionFactory.openSession(true);
 ​
         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
         List<User> users = mapper.selectUser();
         for (User user : users) {
             System.out.println(user);
         }
     }
 }
复制代码

 

2. Mybatis-spring

整合方式一 :

  1. 编写数据源

  2. 配置sqlSessionFactory

  3. sqlSessionTemplate

  4. 需要给接口加实现类【新增】

  5. 将自己写的实现类,注入到Spring中

  6. 测试使用即可!


实体类,接口,导包一致

  • UserMapper

    复制代码
     <?xml version="1.0" encoding="UTF8" ?>
     <!DOCTYPE mapper
             PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
             "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.study.mapper.UserMapper"><select id="selectUser" resultType="User">
             select * from user
         </select></mapper>
    复制代码

     

  • 复制代码
     <?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><typeAliases>
             <package name="com.study.pojo"/>
         </typeAliases></configuration>
    复制代码

     

  • spring-dao.xml

    复制代码
     <?xml version="1.0" encoding="UTF8"?>
     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的配置   c3p0  dbcp  druid
             我们这里使用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/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
             <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"/>
             <!--绑定MyBatis配置文件-->
             <property name="configLocation" value="classpath:mybatis-config.xml"/>
             <property name="mapperLocations" value="classpath:com/study/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="UTF8"?>
     <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"/>
         <!--<import resource="spring-mvc.xml"/>--><!--注入方法-->
         <bean id="userMapper" class="com.study.mapper.UserMapperImpl">
             <property name="sqlSession" ref="sqlSession"/>
         </bean></beans>
    复制代码

     

  • UserMapper.java

    复制代码
     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 {
         public static void main(String[] args) throws IOException {
             ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
             UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
             for (User user : userMapper.selectUser()) {
                 System.out.println(user);
             }
         }
     }
    复制代码

     

遇到的问题

123

org.springframework.beans.factory.BeanCreationException : Error creating bean with name"sqlSession"

检查确认代码无误后检查jar包,经排查发现idea将spring-jdbc的包自动导成了tx包,经过确认,jdbc和tx包需要同时存在才能正常运行,有人发现只有spring-jdbc也报错,那就再额外导入tx包,问题解决....

 

整合方式二 :

复制代码
 public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
     @Override
     public List<User> selectUser() {
         /*SqlSession sqlSession = getSqlSession();
         UserMapper mapper = sqlSession.getMapper(UserMapper.class);
         return mapper.selectUser();*/
         return getSqlSession().getMapper(UserMapper.class).selectUser();
     }
 }
复制代码

 

注入

 <bean id="userMapper2" class="com.study.mapper.UserMapperImpl2">
         <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
     </bean>

 


 

13. 声明式事务

  • 把一组业务当成一个业务来做;要么都成功,要么都失败!

  • 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎!

  • 确保完整性和一致性;

ACID

  • 原子性

  • 一致性

  • 隔离性

    • 多个业务可能操作同一个资源,防止数据损坏

  • 持久性

    • 事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器中!

配置声明式事务

复制代码
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="
  http://www.springframework.org/schema/tx
  https://www.springframework.org/schema/tx/spring-tx.xsd">
 <!--===================导入tx约束===================-->
 <!--配置声明式事务-->
 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource"/>
 </bean><!--结合AOP实现事务的织入-->
 <!--配置事务通知-->
 <tx:advice id="txAdvice" transaction-manager="transactionManager">
     <!--给哪些方法配置事务-->
     <!--配置事务的传播特性: new propagation="REQUIRED"(默认)-->
     <!--read-only="true"只读,不允许修改操作-->
     <tx:attributes>
         <tx:method name="add" propagation="REQUIRED"/>
         <tx:method name="delete" propagation="REQUIRED"/>
         <tx:method name="update" propagation="REQUIRED"/>
         <tx:method name="query" read-only="true"/>
         <tx:method name="*" propagation="REQUIRED"/>
     </tx:attributes>
 </tx:advice>
 <!--配置事务切入-->
 <aop:config>
     <aop:pointcut id="txPointCut" expression="execution(* com.study.mapper.*.(..))">
     <aop:advisor advice-ref="txAdvice" point-ref="txPointCut"/>
 </aop:config>
复制代码

 



posted @   miku_moe  阅读(38)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示