zoukankan      html  css  js  c++  java
  • Spring

    概述

    Maven引入

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

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

    HelloSpring

    实体类

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public class User {
        private Integer id;
        private String username;
        private String password;
    }
    

    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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd"> 
        <!--bean就是java对象 , 由Spring创建和管理-->
        <!--id为获取唯一标识-->
        <bean id="user" class="com.demo.entity.User">
            <property name="id" value="1"/>
            <property name="username" value="admin"/>
            <property name="password" value="admin"/>
        </bean>
    </beans>
    

    测试

    @Test
    public void hello() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    //    User user = context.getBean("user", User.class);
        User user = (User) context.getBean("user");
        System.out.println(user);
    }
    

    创建对象的方式

    在配置文件加载的时候。其中管理的对象都已经初始化了

    set注入

    创建对象:

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Student {
        private String name;
        private Teacher teacher;
        private String[] books;
        private List<String> hobbies;
        private Map<String, String> cards;
        private Set<String> games;
        private String wife;
        private Properties infos;
    }
    

    常量注入

    <bean id="teacher" class="com.demo.entity.Teacher">
        <property name="name" value="李老师"/>
    </bean>
    

    bean注入

    <bean id="student" class="com.demo.entity.Student">
        <property name="name" value="张三"/>
        <!--引用类型用ref,引用Spring容器里的id-->
        <property name="teacher" ref="teacher"/>
    </bean>
    

    数组注入

    <bean id="student" class="com.demo.entity.Student">
        <property name="name" value="张三"/>
        <property name="teacher" ref="teacher"/>
        <property name="books">
            <array>
                <value>西游记</value>
                <value>红楼梦</value>
                <value>水浒传</value>
            </array>
        </property>
    </bean>
    

    List注入

    <property name="hobbies">
        <list>
            <value>听歌</value>
            <value>看电影</value>
            <value>爬山</value>
        </list>
    </property>
    

    Map注入

    <property name="cards">
        <map>
            <entry key="工商银行" value="123"/>
            <entry key="农业银行" value="456"/>
        </map>
    </property>
    

    Set注入

    <property name="games">
        <set>
            <value>魔兽世界</value>
            <value>星际争霸</value>
            <value>英雄联盟</value>
        </set>
    </property>
    

    Null注入

    <property name="wife"><null/></property>
    

    Properties注入

    <property name="infos">
        <props>
            <prop key="age">14</prop>
            <prop key="gender">男</prop>
            <prop key="address">北京</prop>
        </props>
    </property>
    

    构造器注入

    <!--构造器index下标-->
    <bean id="user1" class="com.demo.entity.User">
        <!--从0开始-->
        <constructor-arg index="0" value="1"/>
        <constructor-arg index="1" value="admin1"/>
        <constructor-arg index="2" value="123"/>
    </bean>
    <!--构造器参数名字-->
    <bean id="user2" class="com.demo.entity.User">
        <constructor-arg name="id" value="2"/>
        <constructor-arg name="username" value="admin2"/>
        <constructor-arg name="password" value="123"/>
    </bean>
    <!--构造器参数类型-->
    <bean id="user3" class="com.demo.entity.User">
        <constructor-arg type="java.lang.Integer" value="3"/>
        <!--参数类型相同时按顺序赋值-->
        <constructor-arg type="java.lang.String" value="admin3"/>
        <constructor-arg type="java.lang.String" value="123"/>
    </bean>
    

    扩展注入

    P命名空间注入

    导入约束 : xmlns:p="http://www.springframework.org/schema/p" 
    
    <!--P(属性: properties)命名空间 , 属性依然要设置set方法--> 
    <bean id="user" class="com.kuang.pojo.User" p:name="张三" p:age="18"/>
    

    C命名空间注入

    导入约束 : xmlns:c="http://www.springframework.org/schema/c" 
    
    <!--C(构造: Constructor)命名空间 , 属性依然要设置set方法--> 
    <bean id="user" class="com.kuang.pojo.User" c:name="张三" c:age="18"/>
    

    Spring配置

    别名

    <alias name="user" alias="userAlias"/>
    

    Bean的配置

    别名

    <!--id唯一标识符,name别名-->
    <bean id="user" name="u1 u2,u3;u4" class="com.demo.entity.User">
        <property name="id" value="1"/>
        <property name="username" value="admin"/>
        <property name="password" value="admin"/>
    </bean>
    

    作用域

    <bean id="user" class="xxx.xx" scope="作用域">
        <property name="id" value="1"/>
    </bean>
    

    import

    导入其他Spring配置文件,合并为一个配置文件

    <import resource="bean1.xml"/>
    <import resource="bean2.xml"/>
    

    Bean的自动装配

    • 自动装配是使用spring满足bean依赖的一种方法
    • spring会在应用上下文中为某个bean寻找其依赖的bean

    Spring中bean有三种装配机制,分别是:

    1. 在xml中显式配置;
    2. 在java中显式配置;
    3. 隐式的bean发现机制和自动装配。

    byName

    <bean id="teacher" class="com.demo.entity.Teacher">
        <property name="name" value="李老师"/>
    </bean>
    <bean id="stu" class="com.demo.entity.Student" autowire="byName">
        <property name="name" value="张三"/>
    </bean>
    

    当一个bean节点带有 autowire byName 的属性时

    1. 将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。
    2. 去spring容器中寻找是否有此字符串名称id的对象。
    3. 如果有,就取出注入;如果没有,就报空指针异常。

    byType

    <bean class="com.demo.entity.Teacher">
        <property name="name" value="李老师"/>
    </bean>
    <bean id="stu" class="com.demo.entity.Student" autowire="byType">
        <property name="name" value="张三"/>
    </bean>
    

    使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。

    使用注解

    准备工作:

    1. 在spring配置文件中引入context文件头
    xmlns:context="http://www.springframework.org/schema/context"
    
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    
    1. 开启属性注解支持
    <context:annotation-config/>
    

    @Autowired

    • @Autowired是按类型自动装配的,不支持id匹配
    • 有多个同类型时尝试按set id byName匹配,没有则报错

    @Autowired(required = false) // required = false 表示对象可以为null
    private Teacher teacher;
    

    @Qualifier

    • @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配
    • @Qualifier不能单独使用
    @Autowired()
    @Qualifier("teacher1") // 指定id
    private Teacher teacher;
    

    @Resource

    • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
    • 其次再进行默认的byName方式进行装配;
    • 如果以上都不成功,则按byType的方式自动装配;
    • 都不成功(多个同类型),则报异常。
    @Resource(name = "teacher1")
    private Teacher teacher;
    

    使用注解开发

    在spring4之后,想要使用注解形式,必须得要引入aop的包

    引入context约束:

    xmlns:context="http://www.springframework.org/schema/context"
    
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    

    开启包扫描

    <!--开启注解支持-->
    <context:annotation-config/>
    <!--开启包扫描,让指定包下的注解生效,由IOC容器统一管理-->
    <context:component-scan base-package="com.demo.entity"/>
    

    bean注入

    @Component

    @Component("teacher1") // 等价于 <bean id="teacher1" class="com.demo.entity.Teacher"/>,默认id为类名首字母小写
    public class Teacher {
        private String name;
    }
    

    @Repository

    dao层

    @Controller

    web层

    @Service

    service层

    属性注入

    @Value

    @Value("李老师")
    private String name;
    

    @Autowired

    @Scope作用域

    @Component
    @Scope("prototype")
    public class Teacher {
    }
    

    基于Java类进行配置

    可以省去配置文件

    新建类

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    // 不自动纳入容器
    public class Dog {
        private String name;
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Component // 自动纳入Spring容器
    public class Teacher {
        @Value("李老师")
        private String name;
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Component // 自动纳入Spring容器
    public class Student {
        @Value("张三")
        private String name;
        @Resource
        private Teacher teacher;
    }
    

    新建配置类

    @Configuration // 代表这是一个配置类
    @ComponentScan("com.demo.entity") // 扫描其他包下的自动Bean
    @Import(MyConfig.class) //导入合并其他配置类,类似于配置文件中的 import 标签
    public class AppConfig {
    
        @Bean// 通过方法手动注册一个bean,这里的返回值就Bean的类型,方法名就是bean的id
        public Dog dog() {
            return Dog.builder().name("旺财").build();
        }
    
        @Bean("dog1")// 也可以自定义bean名
        public Dog dog() {
            return Dog.builder().name("旺财1").build();
        }
    }
    

    测试

    @Test
    public void test() {
        // 从配置类获取上下文环境
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Dog dog = context.getBean("dog", Dog.class);
        System.out.println(dog);
        Teacher teacher = context.getBean("teacher", Teacher.class);
        System.out.println(teacher);
        Student student = context.getBean("student", Student.class);
        System.out.println(student);
    }
    

    代理模式

    静态代理

    租房案例

    Rent接口:

    public interface Rent {
        /**
         * 出租房子
         */
        void rent();
    }
    

    房东:

    public class Host implements Rent{
        /**
         * 出租房子
         */
        @Override
        public void rent() {
            System.out.println("房东出租房子");
        }
    }
    

    中介:

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Proxy implements Rent {
        private Host host;
    
        /**
         * 出租房子
         */
        @Override
        public void rent() {
            seeHouse();
            host.rent();
        }
    
        public void seeHouse() {
            System.out.println("中介带你看房");
        }
    }
    

    客户:

    public class Client {
        public static void main(String[] args) {
            Host host = new Host();
    //        host.rent();
            Proxy proxy = new Proxy(host);
            proxy.rent();
        }
    }
    

    新增日志案例

    UserService:

    public interface UserService {
        void getUser();
        void addUser();
    }
    

    UserServiceImpl:

    public class UserServiceImpl implements UserService{
        
        @Override
        public void getUser() {
            System.out.println("获取用户");
        }
    
        @Override
        public void addUser() {
            System.out.println("新增用户");
        }
    }
    

    UserServiceProxy:

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class UserServiceProxy {
        private UserService userService;
    
        public void getUser() {
            log("使用了getUser方法");
            userService.getUser();
        }
        public void addUser() {
            log("使用了addUser方法");
            userService.addUser();
        }
    
        public void log(String msg) {
            System.out.println(msg);
        }
    }
    

    Client:

    public class Client {
        public static void main(String[] args) {
            UserService userService = new UserServiceImpl();
    //        userService.getUser();
    //        userService.addUser();
            UserServiceProxy userServiceProxy = new UserServiceProxy(userService);
            userServiceProxy.getUser();
            userServiceProxy.addUser();
        }
    }
    

    动态代理

    • 动态代理的角色和静态代理的一样 .
    • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
    • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
      • 基于接口的动态代理----JDK动态代理
      • 基于类的动态代理--cglib
      • 现在用的比较多的是 javasist 来生成动态代理 .

    JDK的动态代理需要了解两个类

    • 核心:InvocationHandlerProxy

    核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!

    处理类

    public class ProxyInvocationHandler implements InvocationHandler {
        // 被代理的接口
        private Object target;
    
        public ProxyInvocationHandler(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 {
            System.out.println("中介带你看房");
            Object result = method.invoke(target, args);
            System.out.println("签订合同");
            return result;
        }
    }
    

    动态生成代理对象

    public class Client2 {
        public static void main(String[] args) {
            // 真实角色
            Host host = new Host();
    
            // 设置要代理的对象
            ProxyInvocationHandler pih = new ProxyInvocationHandler(host);
    
            // 生成代理角色
            Rent rent = (Rent) pih.getProxy();
            rent.rent();
        }
    }
    

    AOP

    需要导入一个包

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

    通过 Spring API 实现

    AOP的约束

    xmlns:aop="http://www.springframework.org/schema/aop
    
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    

    新建Active类

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

    配置文件配置

    <!--注册bean-->
    <bean id="userService" class="com.demo.service.UserServiceImpl"/>
    <bean id="beforeLog" class="com.demo.log.BeforeLog"/>
    <bean id="afterLog" class="com.demo.log.AfterLog"/>
    
    <!--配置aop-->
    <!--方式一:使用原生Spring API接口-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pointcut" expression="execution(* com.demo.service.UserServiceImpl.*(..))"/>
        <!--配置环绕-->
        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
    

    测试

    public class ClientAop {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            // 动态代理代理的是接口
            UserService userService = context.getBean("userService", UserService.class);
            userService.getUser();
            userService.addUser();
        }
    }
    

    自定义类

    新建切面类

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

    配置文件配置

    <!--方式二:自定义切面-->
    <!--引入自定义切面类-->
    <bean id="myAspect" class="com.demo.advice.MyAspect"/>
    <aop:config>
        <!--切面配置-->
        <aop:aspect ref="myAspect">
            <!--切入点配置-->
            <aop:pointcut id="pointcut" expression="execution(* com.demo.service.UserServiceImpl.*(..))"/>
            <!--环绕配置-->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>
    

    测试

    使用注解实现

    新建切面类

    @Aspect
    public class AnnotationAspect {
        @Before("execution(* com.demo.service.UserServiceImpl.*(..))")
        public void before() {
            System.out.println("===AnnotationAspect执行前===");
        }
        @After("execution(* com.demo.service.UserServiceImpl.*(..))")
        public void after() {
            System.out.println("===AnnotationAspect执行后===");
        }
        @Around("execution(* com.demo.service.UserServiceImpl.*(..))")
        public void around(ProceedingJoinPoint jp) throws Throwable {
            System.out.println("环绕前");
            System.out.println(jp.getSignature());
            // 执行方法
            Object proceed = jp.proceed();
            System.out.println(proceed);
    
            System.out.println("环绕后");
        }
    }
    

    配置文件配置

    <!--方式三:注解-->
    <!--引入自定义切面类-->
    <bean id="annotationAspect" class="com.demo.aspect.AnnotationAspect"/>
    <!--开启注解支持-->
    <aop:aspectj-autoproxy/>
    

    测试

    整合Mybatis

    Maven引入

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!--MyBatis相关-->
        <dependency><!--数据库驱动-->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <dependency><!--mybatis-->
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency><!--mybatis-spring整合-->
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <!--MyBatis相关-->
        <!--spring相关-->
        <dependency><!--Spring核心-->
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.3</version>
        </dependency>
        <dependency><!--事务-->
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.3</version>
        </dependency>
        <dependency><!--AOP-->
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
        <!--spring相关-->
    </dependencies>
    
    <build>
        <!-- 防止资源导出错误 -->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
    

    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"/>
            <!--开启下划线转驼峰-->
            <setting name="mapUnderscoreToCamelCase" value="true"/>
            <!--开启二级缓存-->
            <setting name="cacheEnabled" value="true"/>
        </settings>
    
        <!--别名配置-->
        <typeAliases>
            <package name="com.demo.entity"/>
        </typeAliases>
        
        <!--Mapper注册-->
        <mappers>
            <package name="com.demo.mapper"/>
        </mappers>
    </configuration>
    

    appcationContext.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: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
           https://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--加载Properties配置文件-->
        <context:property-placeholder location="classpath:db.properties"/>
    
        <!--DataSource-->
        <!--使用Spring的数据源-->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </bean>
    
        <!--SqlSessionFactory-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <!--绑定mybatis配置文件-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
        </bean>
    
        <!--以下两个配置需要再增加一个实现类-->
        <!--sqlSession-->
        <!--<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">-->
        <!--    <constructor-arg ref="sqlSessionFactory"/>-->
        <!--</bean>-->
    
        <!--注册userMapperImpl-->
        <!--<bean id="userMapper" class="com.demo.mapper.UserMapperImpl">-->
        <!--    <property name="sqlSession" ref="sqlSession"/>-->
        <!--</bean>-->
    
        <!--不需要增加实现类-->
        <!--MapperFactoryBean 将会负责 SqlSession 的创建和关闭-->
        <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
            <property name="mapperInterface" value="com.demo.mapper.UserMapper"/>
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>
    
    </beans>
    

    *新增加的实现类:

    public class UserMapperImpl implements UserMapper{
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        /**
         * 获取全部用户
         */
        @Override
        public List<User> getUserList() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.getUserList();
        }
    }
    

    测试

    @Test
    public void testGetUserList() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        List<User> userList = userMapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
    }
    

    声明式事务

    新增事务约束

    xmlns:tx="http://www.springframework.org/schema/tx"
    
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    

    配置事务管理器

    <!--配置事务管理器-->
    <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(* com.demo.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>
    

    测试

    public class UserServiceImpl {
        private UserMapper userMapper;
    
        public void setUserMapper(UserMapper userMapper) {
            this.userMapper = userMapper;
        }
    
        public void test() {
            userMapper.addUser(new User(10, "root10", "root10"));
            int i = 10/0;
            userMapper.deleteUser(10);
        }
    }
    
    <bean id="userService" class="com.demo.service.UserServiceImpl">
        <property name="userMapper" ref="userMapper"/>
    </bean>
    
    @Test
    public void testTransaction() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserServiceImpl userService = context.getBean("userService", UserServiceImpl.class);
    
        userService.test();
    }
    

    结果:出错事务回滚,没有插入进去

    注解式事务

  • 相关阅读:
    Pikachu漏洞练习平台实验——SQL注入(四)
    ELMO,BERT和GPT简介
    Self-Attention 和 Transformer
    Seq2Seq和Attention机制入门介绍
    循环神经网络(RNN)入门介绍
    XGBoost的推导和说明
    在Azure DevOps Server中运行基于Spring Boot和Consul的微服务项目单元测试
    Azure DevOps Server(TFS) 客户端分析
    传统码头建设企业:Azure DevOps Server 流水线技术沟通
    ItelliJ Idea 2019提交TFVC变更,系统提示Validation must be performed before checking in
  • 原文地址:https://www.cnblogs.com/shenleg/p/14284252.html
Copyright © 2011-2022 走看看