狂神spring学习笔记

news/2024/10/11 2:30:44

1. Spring

1. 简介

一个融合器,一个简化开发的框架

spring官网

github地址

2. Maven坐标

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>6.1.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>6.1.6</version>
</dependency>

3. 优点

  1. 开源的免费的框架(容器)
  2. 轻量级,非侵入式(引入后不会对原程序造成影响,原来能跑的还是能跑)
  3. 控制反转(IOC),面向切面编程(AOP)
  4. 支持事务处理,对框架整合的支持

4. 扩展

spring boot

  • 一个快速开发的脚手架
  • 可以快速开发单一的微服务
  • 约定大于配置

spring cloud

  • 给予spirng boot实现

学习springboot的前提是需要完全掌握Spring和springmvc

5. 七大模块

img

2. IOC理论推导

老开发模式

  1. DAO接口层
  2. DAO层impl
  3. Service接口层
  4. Serviceimpl层

![image-20240427161130288](/Users/yuanzilin/Library/Application Support/typora-user-images/image-20240427161130288.png)

用户的需要会影响我们原来的代码

在使用一个set接口后

public void setUserDao(UserDao userDao){this.userDao = userDao;}

我们将创建对象的控制权给了用户,程序不再具有主动性,而是被动的接受对象,系统耦合性大大降低,更加专注在业务实现上,这也是工厂模式

这是IOC的原型

IOC本质

控制反转loC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是loC的另一种说法。没有IoC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency Injection,DI)。

3.HelloSpring

使用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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

放在开头,命名为ApplicationContext.xml

<bean id="hello" class="com.ll.pojo.Hello" ><property name="str" value="HaHa"></property></bean>

在xml中用bean中创建对象,程序仅用于接收对象

具体的值,基础数据类型

引用spring容器中创建好的对象

ApplicationContext context = new ClassPathXmlApplicationContext( "beans.xml");

所谓IOC就是让那个spring来装配,管理,配置对象 ,要实现不同的操作不再需要去程序中改动了,只需要需要xml配置文件

4.IOC创建对象的方式

  1. 默认使用无参构造创建对象

  2. 下标赋值

    <bean id="User" class="com.ll.pojo.User"><constructor-arg index="0" value="ll"></constructor-arg></bean>
    
  3. 类型(多个相同类型参数时不可用,不推荐)

<bean id="User" class="com.ll.pojo.User"><constructor-arg type="java.lang.String" value="ll"></constructor-arg></bean>
  1. 直接通过参数名设置(最直观易读)
<bean id="User" class="com.ll.pojo.User"><constructor-arg name="name" value="ll"></constructor-arg></bean>

Spring会在配置文件加载时,创建所有bean

5. Spring配置

别名

 <bean id="User" class="com.ll.pojo.User"><constructor-arg name="name" value="ll"></constructor-arg></bean><alias name="User" alias="ffff"></alias>

bean的配置

  • id :bean 的唯一标识符
  • class:bean对象的全限定名
  • name:也是别名

import

用于团队开发,合并配置文件

6.依赖注入(DI)

1.构造器注入

即4.4

2.set注入【重点】

  • 依赖注入
    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象中的所有对象,有容器来注入

【环境搭建】

  1. 复杂背景
public class Address {private String address;
}
  1. 真实测试对象
public class Student {private String name;private Address address;private String[] books;private List<String> hobbys;private Map<String,String> card;private Set<String> games;private String wife;private Properties info;
}
  1. 实践配置
<bean id="address" class="com.ll.pojo.Address" ><property name="address" value="翻斗乐园111号"></property></bean><bean id="student" class="com.ll.pojo.Student"><property name="name" value="ll"></property><property name="address" ref="address"></property><property name="books"><array><value>booka</value><value>bookb</value></array></property><property name="card"><map><description>this card</description><entry key="身份证" value="4310269999999"></entry><entry key="学生证" value="21009201234"></entry></map></property><property name="games"><set><value>lol</value><value>bob</value><value>coc</value></set></property><property name="hobbys"><list><value>eat</value><value>sleep</value><value>cook</value></list></property><property name="wife"><null/></property><property name="info"><props><prop key="身份证">431026111111</prop><prop key="idcard">11111111</prop></props></property></bean>

3.扩展方式

  1. p命名注入 p即是property的意思

在xml文件中加入

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

注入方式如即

<bean id="user" class="com.ll.pojo.User" p:name="ll" p:age="18"></bean>
  1. c命名注入 c即是constructor的意思

    在xml文件中加入,并且要在实体类中加入无参和有参构造器

    xmlns:c="http://www.springframework.org/schema/c"
    

    注入方式如下

    <bean id="user2" class="com.ll.pojo.User" c:_1="18" c:name="cll"  ></bean>
    

    不知名原因:使用c:age会出现类型转换的报错,但是使用c:_1没有这个问题

    4.bean的作用域(scope)

    1. 单例模式(singleton)(默认机制)
    2. 原型模式(prototype):每次从容器中get都会产生一个新对象

    7.bean的自动装配

    • 自动装配时spring满足bean依赖的一种方式
    • spring会在上下文中自动寻找,并自动为bean装配属性

    三种装配方式

    1. xml装配
    2. java装配
    3. 隐式的自动装配【重点】

    1.情景设置

    一个人有两个宠物

    2.autowire 自动装配

    1. byName 自动装配
    <!-- byName方式使用beanid自动装配--><bean id="cat" class="com.ll.pojo.Cat"></bean><bean id="dog" class="com.ll.pojo.Dog"></bean><bean id="people" class="com.ll.pojo.People" autowire="byName"></bean>
    
    1. byType自动装配
    <!-- byType方式使用类型自动装配--><bean id="cat2222" class="com.ll.pojo.Cat"></bean><bean id="dog1111" class="com.ll.pojo.Dog"></bean><bean id="people" class="com.ll.pojo.People" autowire="byType"></bean>
    

    3.注解自动装配

    使用注解的须知:

    1. 导入约束。context约束
    2. 配置注解的支持
    <?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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/></beans>
    

    @Autowired注解

    public class People {@Autowiredpublic Cat cat;@Autowiredpublic Dog dog;}
    

    默认通过byType填充,通过反射实现,可以不需要set方式,前提是自动装配的属性在Spring容器中存在

    @Nullable //表示这个字段可以为null
    

    @Qualifier(value = "beanid")

    @Autowired@Qualifier(value = "dog1111")public Dog dog;
    

    当自动装配无法通过ByType完成时,这个注解表示用ByName方式获得唯一bean

    @Resource

    Java原生注解,在jdk1.8后移除,作用比Autowired略强大,通过名字,类型装配

    8.使用注解开发

    Spring4以后,要使用注解开发必须要导入aop

    1. bean
    @Component
    public class User {public String name = "ll";
    }
    

    相当于<bean id = "user" class = "com.ll.pojo.User"

    1. 属性如何注入
    <context:component-scan base-package="com.ll"></context:component-scan>
    
    @Component
    public class User {@Value("ll")public String name;
    }
    
    1. 衍生的注解

    @Component有几个衍生注解,在MVC三层中

    • dao @Repository
    • service @Service
    • controller @Controller

    这四个注解是几乎一模一样的,component-scan可以直接扫描

    1. 自动装配置

    上第7节

    1. 作用域

    @Scope

    1. 小结
    • xml更加万能通用
    • 注解更加简单
    • 最佳实践
      • xml管理bean
      • 注解只负责完成属性的注入

    9.使用java的方式配置Spring

    完全不使用Spring的xml配置,全权交给java配置

      • @Configuration

      • @ComponentScan("com.ll")

      Configuration本身也是个Conponent,代表这个类是个配置类,类似于之前的整个beans.xml文件。与@ComponentScan搭配使用,下文件名为UserConfiguration.java

      @Configuration
      @ComponentScan("com.ll")
      public class UserConfiguration {}
      
      1. @Bean表示将一个类注册为bean,下文件名为UserConfiguration.java

        @BeanUser User(){return new User();
        

      这个方法的名字相当于bean的id,返回值类型相当于bean的class

      1. Test文件
      public class MyTest {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(UserConfiguration.class);User user = context.getBean("User", User.class);System.out.println(user.toString());}
      }

      10.代理模式

      代理模式是SpirngAOP的底层

      代理模式的分类

      • 静态代理
      • 动态代理

      ![image-20240429201011357](/Users/yuanzilin/Library/Application Support/typora-user-images/image-20240429201011357.png)

      角色分析:

      • 抽象角色:一般使用接口或接口类来实现
      public interface Rent {void rent();
      }
      
      • 真实角色:被代理的角色
      public class Host implements Rent {@Overridepublic void rent() {System.out.println("房东出租房子");}
      }
      
      • 代理角色:代理真实的角色,代理真实绝收,我们一般会做一些附属操作
      public class Proxy implements Rent{private Host host;public Proxy(Host host) {this.host = host;}@Overridepublic void rent() {kanfang();host.rent();hetong();}public void kanfang(){System.out.println("中介带你看房");}public void hetong(){System.out.println("中介带你签合同");}
      }
      • 客户:访问代理对象的人
      public class Client {public Proxy proxy = new Proxy(new Host());public Client(Proxy proxy) {this.proxy = proxy;}
      }
      

      代理模式的好处

      • 可以使真实角色的操作更加纯粹,不要去关注一些公共的业务
      • 公共业务交给代理角色,实现了业务的分工
      • 公共业务发生扩展时,方便集中管理

      缺点:

      • 一个真实角色就会尝试一个代理角色,代码量会翻倍

      10.2加深理解

    ![image-20240429205109743](/Users/yuanzilin/Library/Application Support/typora-user-images/image-20240429205109743.png)

    10.3 动态代理

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

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

    • 分两大类

      • 基于接口的动态代理 --JDK动态代理
      • 基于类的 -- cglib
      • java字节码实现 --javasist

      这里学习JDK动态代理

      两个类:Proxy类 提供创建动态代理类和实例的静态方法

      InvocationHandler类 生成代理类

      狂神的例子在java9以后跑不通了,我在网上摘了一个

      img

    假如一个大老板想吃饭,但又觉得煮饭洗碗太麻烦了,就把煮饭希望这些事都扔给代理类【仆人】处理,自己实现吃的功能即可

    public interface Eat {void eat();
    }
    public class Master implements Eat{@Overridepublic void eat(){System.out.println("主人:干饭!");}
    }
    
    public class DynamicServant implements InvocationHandler {// 被代理的对象(这里就不是Master了,因为要换成富二代少爷也能代理……)Object targetObj;DynamicServant(Object targetObj) {// 这个构造函数不用多讲了吧this.targetObj = targetObj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 仆人在主人吃饭前做的动作放这System.out.println("仆人:买菜煮饭……");// 这是被代理类要做的事(即吃饭)Object invoke = method.invoke(this.targetObj, args);// 仆人在主人吃饭后做的动作System.out.println("仆人:收拾饭桌洗碗……");return invoke;}public static void main(String[] args) {// 首先new一个masterMaster m1 = new Master();// 接着new一个servantEat e1 = (Eat) Proxy.newProxyInstance(m1.getClass().getClassLoader(),m1.getClass().getInterfaces(),new DynamicServant(m1));// 最后用new出来的servant调用eat方法e1.eat();}}

    在动态代理中,Proxy.newProxyInstance返回的不是代理类实例(仆人),而是返回 【被代理的接口】(Eat实例)

具体原因

11.AOP

1. 什么是AOP

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

img

2. AOP在Spring中的作用

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

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 ….
  • 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
  • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
  • 目标(Target):被通知对象。
  • 代理(Proxy):向目标对象应用通知之后创建的对象。
  • 切入点(PointCut):切面通知 执行的 “地点”的定义。
  • 连接点(JointPoint):与切入点匹配的执行点。

img

3. 用spring实现AOP

方式一:用Spirng的API接口

导包

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.22</version><scope>runtime</scope>
</dependency>

注册bean和aop配置

 <bean id="userService" class="com.ll.service.UserServiceImpl"/><bean id="log" class="com.ll.log.Log"/><bean id="afterLog" class="com.ll.log.AfterLog"/><aop:config>
<!--    先定义切入点--><aop:pointcut id="pointcut" expression="execution(* com.ll.service.UserServiceImpl.*(..))"/>
<!--    执行环绕--><aop:advisor advice-ref="log" pointcut-ref="pointcut"/><aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>

注意pointcut_id不要和bean_id一样,否则无法通过编译

业务接口和实现

public interface UserService {public void add();public void delete();public void update();public void select();
}
public class UserServiceImpl implements UserService{@Overridepublic void add() {System.out.println("增加了一个用户");}@Overridepublic void delete() {System.out.println("删除了一个用户");}@Overridepublic void update() {System.out.println("更新了一个用户");}@Overridepublic void select() {System.out.println("查找了一个用户");}
}

两种log

public class Log implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(target.getClass().getName()+ "de"+method.getName()+"被执行了");}
}
public class AfterLog implements AfterReturningAdvice {@Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println("执行了"+method.getName()+"返回了结果"+returnValue);}
}

测试类

ublic class MyTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");UserService userService = (UserService) context.getBean("userService");userService.add();}
}

注意,代理的是接口

方式二:自定义类实现AOP

使用自定义类

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

创建切面

 <bean id="diy" class="com.ll.Diy.DiyPointCut"/><bean id="userService" class="com.ll.service.UserServiceImpl"/><aop:config><aop:aspect  ref="diy" ><aop:pointcut id="point" expression="execution(* com.ll.service.UserServiceImpl.*(..))"/><aop:before method="before" pointcut-ref="point"/><aop:after method="after" pointcut-ref="point"/></aop:aspect></aop:config>

测试类同上不用变

方式三:注解实现

自定义类

@Aspect
public class AnnotionPointCut {@Before("execution(* com.ll.service.UserServiceImpl.*(..))")public void before(){System.out.println("方法执行前");}@After("execution(* com.ll.service.UserServiceImpl.*(..))")public void after(){System.out.println("方法执行后");}
}
<bean id="annotionPointCut" class="com.ll.Diy.AnnotionPointCut"/><bean id="userService" class="com.ll.service.UserServiceImpl"/>
<!--    开启注解支持--><aop:aspectj-autoproxy/>

测试类同上

12.整合Mybatis

1. mybatis的过去做法

  1. 导入相关jar包
 <properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency></dependencies><build><resources><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources></build>
  1. 编写配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--       类型别名--><typeAliases><package name="com.ll.pojo"/></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/><property name="username" value="root"/><property name="password" value=""/></dataSource></environment></environments><mappers><mapper class="com.ll.mapper.UserMapper"/></mappers></configuration>

Mybatis-config.xml

记得注册mapper

  1. 编写测试类
  • 创建pojo
@Data
public class User {
private int id;
private String name;
private String password;
}
  • 编写mapper

    public interface UserMapper {public List<User> selectUser();
    }
  • mapper配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ll.mapper.UserMapper">
<select id="selectUser" resultType="user">select * from mybatis.user;
</select>
</mapper>
  • 测试类
public class MyTest {@Testpublic void test() throws IOException {String resources = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resources);SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession session = sessionFactory.openSession(true);UserMapper userMapper = session.getMapper(UserMapper.class);List<User> userList = userMapper.selectUser();for (User user: userList) {System.out.println(user.toString());}}
}

2. spirng整合mybatis

方式一

  1. 编写数据源配置

  2. sqlSessionFactory

  3. sqlSessionTemplate

  4. 给接口加实现类

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

  6. 测试使用即可

<?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/beanshttps://www.springframework.org/schema/beans/spring-beans.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?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/><property name="username" value="root"/><property name="password" value=""/></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/ll/mapper/UserMapper.xml"/></bean>
<!--配置SqlSessionTemplate--><bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" >
<!--        因为SqlSessionTemplate没有set方法,只能使用构造器注入--><constructor-arg index="0" ref="sqlSessionFactory"/></bean>
<!--    注册mapper--><bean id="userMapper" class="com.ll.mapper.UserMapperImpl"><property name="session" ref="sqlSession"/></bean>
</beans>
public class UserMapperImpl implements UserMapper{
//    所有方法使用SQlSessionTemplate代替SQlSessionprivate SqlSessionTemplate session;public void setSession(SqlSessionTemplate session) {this.session = session;}@Overridepublic List<User> selectUser() {UserMapper mapper = session.getMapper(UserMapper.class);return mapper.selectUser();}
}
public class MyTest {@Testpublic void test() throws IOException {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserMapper userMapper =  context.getBean("userMapper", UserMapper.class);List<User> userList = userMapper.selectUser();for (User user: userList) {System.out.println(user.toString());}}
}

方式二

使用SqlSessionDaoSupport类

public class UserMappepimpl2 extends SqlSessionDaoSupport implements UserMapper {@Overridepublic List<User> selectUser() {return getSqlSession().getMapper(UserMapper.class).selectUser();}
}

注册到spring里

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

测试类

public class MyTest {@Testpublic void test() throws IOException {ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserMapper userMapper =  context.getBean("userMapper2", UserMapper.class);List<User> userList = userMapper.selectUser();for (User user: userList) {System.out.println(user.toString());}}
}

13 . 声明式事务

1. 回顾事务

  • 把一组业务当成一个业务来做,要么都成功,要么都失败
  • ACID原则
    • 持久性
    • 一致性
    • 原子性
    • 隔离性

2. spring中事务管理

  • 声明式事务:aop
  • 编程式事务

声明式事务

  • 配置声明式事务
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><constructor-arg ref="dataSource"/>
</bean>
  • aop织入事务
<!--    结合aop实现事务的织入-->
<!--    配置事务通知--><tx:advice id="txAdvice"><tx:attributes>
<!--            配置事务传播特性--><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice>
<!--    配置aop切入--><aop:config><aop:pointcut id="txPointCut" expression="execution(* com.ll.mapper.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/27494.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

2024-05-04 如何为antd的table设置序号

给columns加多一列即可:const columns = [{title: "序号",key: "index",render: (_, record, index) => index + 1,},...]如图:

Multisim14--软件简介及安装教程(内含安装包)

安装包见文章末尾一、软件简介 Multisim是美国国家仪器(NI)有限公司推出的以Windows为基础的仿真工具,适用于板级的模拟/数字电路板的设计工作。它包含了电路原理图的图形输入、电路硬件描述语言输入方式,具有丰富的仿真分析能力。工程师们可以使用Multisim交互式地搭建电路…

随机抽奖

问题:随机抽奖公式 解决1:只一个抽奖结果=INDEX(A:A,RANDBETWEEN(2,11))解决2:多个抽奖结果且不能有重复=TAKE(SORTBY(A2:A11,RANDARRAY(10)),6)将抽奖名单按随机序排序,再提取前六个。

2024-05-04 如何去掉uniapp的h5开发中url存在的#号?

如果你正在用uniapp开发h5页面,你会发现h5页面的url里带有一个#号,比如:http://localhost:8080/#/pages/index/index 原因:uniapp默认模式导致 解决方案:修改uniapp默认模式为history,如下图所示:

Python自动化测试中JSON数据处理遇到的错误

在接口自动化测试领域,使用Excel管理测试数据是一种常见的做法。本文将分享一个实际案例,介绍在Python自动化测试框架中,如何从响应结果中提取所需数据,并探讨在处理JSON格式数据时遇到的一个典型问题及其解决方案。 首先,让我们了解测试数据的基本格式。在Excel中,我们定…

stm32开发笔记

GPIO全名为General Purpose Input Output,即通用输入输出。有时候简称为“IO口”。通用,说明它是常见的。输入输出,就是说既能当输入口使用,又能当输出口使用。端口,就是元器件上的一个引脚。 输入模式和输出模式是GPIO的基本特性,当然GPIO还有其它模式可选。 (一)模式…

UE4 C++ 杂

TMap中的Find和FindRef 在对蓝图节点进行C++重写时,发现UE对于TMap的Find有很多方式。首先是基础的Find,其就是返回对象类型的指针,如果不存在于TMap中其会返回nullptr接下来是FindChecked,其返回的是对象类型的引用,并且会在内部检测指针是否为空,如果没有会触发断言Fin…

在Docker内部使用gdb调试器报错-Operation not permitted

在docker内部使用gdb调试时刻遇到了gdb如下报错信息:warning: Error disabling address space randomization: Operation not permitted原因 地址随机化是linux一项安全特性,它允许内核进程启动每次加载库的时候都在随机化的分布在进程虚拟内存地址空间上(早期固定的库要加载到…