Spring 入门实例

什么是Spring

Spring是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架。,其目的是简化企业的应用程序开发,降低侵入性,Spring提供的IOC和AOP功能,可以将组件之间的耦合度降到最低,便于后期的维护和升级,实现了软件的高内聚低耦合思想。
优点:

  1. Spring能帮我们根据配置文件创建及组装对象之间的依赖关系。帮助我们管理Bean对象的生命周期,以及维护各个Bean对象之间的关系。
  2. Spring是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。
  3. 支持声明式事务处理,只需要通过配置就可以完成对事务的管理,而无须手动编程。.
  4. Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如Struts、Hibernate、MyBatis、Quartz等)的直接支持。

Spring IoC入门实例

IoC(控制反转):对象的实例不再由调用者来创建,而是由 Spring容器来创建。Spring容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由调用者转移到Spring容器,控制权发生了反转,这就是Spring的控制反转。

IoC配置文件实例

创建一个maven项目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
导入依赖
在这里插入图片描述

<dependencies>

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

    <!--  单元测试依赖-->
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.18</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

spring-webmvc帮我们导人了许多核心依赖(aop,deans, context,core等)因此导入这一个依赖就够了。junit用于测试,lombok偷懒用的可有可无。

创建普通的Java类
Preson类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Preson {
    private Book book;
    private String[] hobby;
    private List<String> list;
    private Map<String, String> map;
    private Properties properties;
}

Book类

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Book {
    private int bookID;
    private String bookName;
    private int bookCounts;
    private String detail;
}

beans.xml

<?xml version="1.0" encoding="UTF8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

<!--    通过构造方法注入属性值,不需要提供setXXX()方法,-->
    <bean id="book" class="com.jie.pojo.Book">
<!--        通过构造器参数的顺序注入(不推荐使用,当有多个构造器时,默认使用第一个符合的构造器,如果要使用其他的构造器可以通过type类型匹配来区分不同的构造方法)-->
        <constructor-arg  value="1"/>
<!--        通过参数名注入(推荐使用,无歧义一眼就可以看到是给谁赋值)-->
        <constructor-arg name="bookCounts" value="10"/>
<!--        通过指定参数顺序名注入(不推荐使用)-->
        <constructor-arg index="1" value="java"/>
        <constructor-arg name="detail" value="咖啡"/>

<!--        通过set方法注入,要提供XXset方法-->
<!--        复杂类型注入-->
    </bean>
    <bean id="preson" class="com.jie.pojo.Preson">
<!--        类类型:ref属性指向对book的引用(id为book的bean)-->
        <property name="book" ref="book"/>
<!--        数组类型-->
        <property name="hobby">
            <array>
                <value>打篮球</value>
                <value>打网球</value>
            </array>
        </property>
<!--        list集合-->
        <property name="list">
            <list>
                <value>睡觉</value>
                <value>玩游戏</value>
            </list>
        </property>
<!--        map集合-->
        <property name="map">
            <map>
                <entry key="今晚" value="吃鸡"/>
                <entry key="王者" value="五杀"/>
            </map>
        </property>
<!--        properties-->
        <property name="properties">
            <props>
                <prop key="name">唐三</prop>
                <prop key="sex"></prop>
            </props>
        </property>
    </bean>

</beans>

注入方式有两种:构造器注入和set方法注入
通过构造方法注入属性值,不需要提供setXXX()方法。
通过set方法注入,要提供对应的XXset方法

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <import resource="classpath:beans.xml"/>
</beans>

import导入其他xml文件。

测试

@Test
    public void test() {
    // 1. 加载Spring配置文件,根据创建对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 2. 得到bean对象
        Preson preson = context.getBean("preson", Preson.class);
        System.out.println(preson.toString());
    }

运行结果

Preson(book=Book(bookID=1, bookName=java, bookCounts=10, detail=咖啡), hobby=[打篮球, 打网球], list=[睡觉, 玩游戏], map={今晚=吃鸡, 王者=五杀}, properties={name=唐三, sex=男})

xml配置文件和注解混合使用实例

修改beans.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:contet="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context
          https://www.springframework.org/schema/context/spring-context.xsd">
          
    <!--  开启注解扫描包中扫描类、方法、属性上是否有注解 -->
    <contet:component-scan base-package="com.jie.pojo"/>
    
    <bean id="preson" class="com.jie.pojo.Preson">
<!--        类类型:ref属性指向对book的引用(id为book的bean)-->
        <property name="book" ref="book"/>
<!--        数组类型-->
        <property name="hobby">
            <array>
                <value>打篮球</value>
                <value>打网球</value>
            </array>
        </property>
<!--        list集合-->
        <property name="list">
            <list>
                <value>睡觉</value>
                <value>玩游戏</value>
            </list>
        </property>
<!--        map集合-->
        <property name="map">
            <map>
                <entry key="今晚" value="吃鸡"/>
                <entry key="王者" value="五杀"/>
            </map>
        </property>
<!--        properties-->
        <property name="properties">
            <props>
                <prop key="name">唐三</prop>
                <prop key="sex"></prop>
            </props>
        </property>
    </bean>

</beans>

<contet:component-scan base-package=“com.jie.pojo”/>开启注解扫描,扫描com.jie.pojo包及其子包中的注解,如果某个类的头上带有特定的注解@Component,@Repository,@Service,@Controller,就会将这个对象作为Bean注册进Spring容器。不开启注解扫描注解不会生效

修改Book类

@NoArgsConstructor
@AllArgsConstructor
@Data
@Component
public class Book {
    @Value("1")
    private int bookID;
    @Value("java")
    private String bookName;
    @Value("8")
    private int bookCounts;
    @Value("咖啡")
    private String detail;
}

其他不变,

通常对于基本数据类型、String 使用@Value()注解注入,对于类类型使用 @Autowired或@Resource注入,对于集合等复杂类型,使用xml配置文件

spring aop 入门实例

aop(面向切面编程) :spring aop 通过动态代理,将那些与业务无关,却在业务模块的许多方法中需要用到的代码(切面类的方法)。在方法调用时,动态的插入这些代码。
可以让我门专注自己本身的业务,而不去想一些其他与业务无关的事情,这些其他的事情包括:安全,事务,日志等。

使用配置文件实现aop

要使用spring aop除了上面的依赖还需要导入aspectjweaver依赖。

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

不导入会报错如下错误
在这里插入图片描述
MyTransaction(切面类)

@Component
public class MyTransaction {

    public void beginTransaction(){
        System.out.println("开启事务 ");
    }

    public void commit(){
        System.out.println("提交事务");
    }

}

Preson类中添加可以被通知插入的方法

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Preson {
    @Autowired
    private Book book;
    private String[] hobby;
    private List<String> list;
    private Map<String, String> map;
    private Properties properties;

    public void aopTest(){
        System.out.println("事务正在处理");
    }
}

aop.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">

    <!-- 切面类 -->
    <bean id="myTransaction" class="com.jie.pojo.MyTransaction"></bean>
<!--aop配置-->
   <aop:config>
<!--       切入点  声明那些地方可以被插入通知-->
      <aop:pointcut id="tx" expression="execution(* com.jie.pojo. Preson.*(..))"/>
  <!-- 切面类 -->
       <aop:aspect ref="myTransaction">
<!--       设置切面类的方法是什么通知(前置,后置,环绕等等), 并设置这些通知可以从那些切入点插入。-->
           <aop:before method="beginTransaction" pointcut-ref="tx"/>
           <aop:after method="commit" pointcut-ref="tx"/>
       </aop:aspect>
   </aop:config>
</beans>

在这里插入图片描述

切入点表达式execution(* com.jie.pojo.Preson.*(…))表示 Preson类的所有方法都是切入点。

applicationContext.xml中导入aop.xml

<?xml version="1.0" encoding="UTF8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <import resource="classpath:beans.xml"/>
    <import resource="classpath:aop.xml"/>

</beans>

测试

  @Test
    public void test() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Preson preson = context.getBean("preson", Preson.class);
        preson.aopTest();
    }

测试结果
在这里插入图片描述

使用注解实现aop

首先在applicationContext.xml中开启aop代理模式

<?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="classpath:beans.xml"/>
<!--    开启aop代理模式-->
    <aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>

</beans>

不开启会使aop注解失效

修改MyTransaction类

@Component
@Aspect//标注这是一个切面类
public class MyTransaction {
    //前置通知,括号里填切入点
@Before("execution(* com.jie.pojo.Preson.*(..))")
    public void beginTransaction(){
        System.out.println("开启事务 ");
    }
    //后置通知
@After("execution(* com.jie.pojo.Preson.*(..))")
    public void commit(){
        System.out.println("提交事务");
    }

}

测试

  @Test
    public void test() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Preson preson = context.getBean("preson", Preson.class);
        preson.aopTest();
    }

测试结果
在这里插入图片描述

spring整合mybatis

导入依赖

    <!--  mysql数据库驱动依赖-->
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.23</version>
    </dependency>

<!--   mybatis依赖-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>

<!--    mybatis与spring整合的依赖-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.6</version>
    </dependency>

<!--    druid数据库连接池 -->
    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.5</version>
    </dependency>

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

过滤资源 不然放在src/main/java和src/main/resources路径下的xml和properties文件加载不到。

 <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

编写mybatis配置文件:mybatis-config.xml

<?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>
    <!--    日志和缓存设置-->
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <!--    指定包下的类起别名(类名首字母小写),配置后XXXMapper.xml中的类类型可以使用别名,没有配置必须使用全类名-->
    <typeAliases>
        <package name="com.jie.pojo"/>
    </typeAliases>

<mappers>
    <package name="com.jie.mapper"/>
</mappers>
</configuration>

数据源在spring-dao.xml中配置,

spring-dao.xml

<?xml version="1.0" encoding="UTF8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--Druid数据库连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="root"/>
        <property name="password" value="968426"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mydate?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=true&amp;serverTimezone=GMT%2B8"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
    </bean>

    <!--    sqlSessionFactory,用于创建sqlSession-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--       绑定Druid数据库连接池-->
        <property name="dataSource" ref="dataSource" />
        <!--        绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    
 <!--    sqlSession-->
    <bean id="sqlSessionTemplate"   class="org.mybatis.spring.SqlSessionTemplate" >
      <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

spring-dao.xml中配置数据源,注册mybatis的核心bean ,sqlSessionFactory和sqlSessionTemplate
sqlSessionFactory:绑定数据源和mybatis配置文件(mybatis配置文件中的所有设置都可以在sqlSessionFactory中配置)
sqlSessionTemplate:是sqlSession的模板,可以把它当成sqlSession使用。

applicationContext.xml中导入spring-dao.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="classpath:beans.xml"/>
    <import resource="classpath:spring-dao.xml"/>
    <!--    开启aop代理模式-->
    <aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>

</beans>

创建数据库

CREATE TABLE `book` (
  `bookID` int NOT NULL AUTO_INCREMENT,
  `bookName` varchar(100) NOT NULL,
  `bookCounts` int NOT NULL,
  `detail` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`bookID`),
  KEY `bookID` (`bookID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

目录结构
在这里插入图片描述
BookMapper接口:声明方法

public interface BookMapper {
    //增
    int addBook(Book book);

    //删
    int delBook(@Param("bookID") int id);

    //改
    int updateBook(Book book);

    //查
    List<Book> queryBook();
    List<Book> queryBookByLike(String bookName);
}

BookMapper.xml:专注于编写sql

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jie.mapper.BookMapper">
<!---->
    <insert id="addBook" parameterType="book">
        insert into mydate.book(bookName, bookCounts, detail) VALUES(#{bookName},#{ bookCounts},#{detail});
    </insert>
<!---->
    <delete id="delBook" parameterType="int">
        delete from mydate.book where bookID=#{bookID};
    </delete>
<!---->
    <update id="updateBook" parameterType="book">
        update mydate.book set bookName=#{bookName},bookCounts=#{bookCounts},detail=#{detail} where bookID=#{bookID};
    </update>
<!---->
    <select id="queryBook"  resultType="book">
        select * from  mydate.book;
    </select>

    <select id="queryBookByLike"  resultType="book" parameterType="string">
        select * from  mydate.book where bookName like "%"#{bookName}"%" ;
    </select>
</mapper>

BookMapperImpl实现类:专注业务(对应mvc的service层,注解应该使用@Service,这里就不改了。)

@Repository
public class BookMapperImpl implements BookMapper {
   @Autowired
    private SqlSessionTemplate sqlSessionTemplate;

    public int addBook(Book book) {
        return sqlSessionTemplate.getMapper(BookMapper.class).addBook(book);
    }

    public int delBook(int id) {
        return sqlSessionTemplate.getMapper(BookMapper.class).delBook(id);
    }

    public int updateBook(Book book) {
        return sqlSessionTemplate.getMapper(BookMapper.class).updateBook(book);
    }

    public List<Book> queryBook() {
        return sqlSessionTemplate.getMapper(BookMapper.class).queryBook();
    }

    public List<Book> queryBookByLike(String bookName) {
        return sqlSessionTemplate.getMapper(BookMapper.class).queryBookByLike(bookName);
    }
}

测试

 @Test
    public void test() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookMapper bookMapper = context.getBean(BookMapperImpl.class);
        List<Book> books = bookMapper.queryBook();
        for (Book book:books) {
            System.out.println(book.toString());
        }
    }

测试结果
在这里插入图片描述

spring中事务的使用

先看一下没有事务的情况

修改BookMapperImpl的delBook,故意添加一个错误 int a=1/0;

 public int delBook(int id) {
        int i = sqlSessionTemplate.getMapper(BookMapper.class).delBook(id);
        int a=1/0;
        return i;
    }

测试

  @Test
    public void test() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookMapperImpl bookMapper = context.getBean(BookMapperImpl.class);
        bookMapper.delBook(10);
    }

这个方法中出现了异常,但是数据库中的数据却被删除了。
在这里插入图片描述

再看配置事务的情况

spring-dao.xml中添加事务配置(同样事务一般写在spring-service.xml配置文件中,偷懒所以将它们都写在了spring-dao.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:tx="http://www.springframework.org/schema/tx"
       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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--Druid数据库连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="root"/>
        <property name="password" value="968426"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mydate?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=true&amp;serverTimezone=GMT%2B8"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
    </bean>

    <!--    sqlSessionFactory,用于创建sqlSession-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--       绑定Druid数据库连接池-->
        <property name="dataSource" ref="dataSource" />
        <!--        绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

    <bean id="sqlSessionTemplate"   class="org.mybatis.spring.SqlSessionTemplate" >
      <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>


<!--   下面是添加事务的配置-->

<!--    配置声明事务 使用Druid数据源-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
<!--配置事务通知-->
   <tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
<!--       给哪些方法配置事务-->
       <tx:attributes>
           <tx:method name="addBook" propagation="REQUIRED"/>
           <tx:method name="delBook"/>
           <tx:method name="updateBook"/>
           <tx:method name="queryBook" read-only="true" />
       </tx:attributes>
   </tx:advice>
    
<!--    配置事务切入-->
    <aop:config proxy-target-class="true">
        <aop:pointcut id="txPointcut" expression="execution(* com.jie.mapper.BookMapperImpl.*(..))"/>
        <aop:advisor advice-ref="transactionInterceptor" pointcut-ref="txPointcut"/>
    </aop:config>
</beans>

注意点
1.tx使用的是xmlns:tx="http://www.springframework.org/schema/tx"别用错了。
2.aop要使用cglib动态代理<aop:config proxy-target-class=“true”> 不配置proxy-target-class="true"将使用InvocationHandler动态代理可能出现如下错误:
使用.class获取bean,出现以下错误。
在这里插入图片描述
使用bean的name获取bean,出现以下错误。
在这里插入图片描述

问题分析:

Spring在进行动态代理的时候,会根据得到的类,进行自动设置使用哪种动态代理的实现方法。
1.创建的类没有实现接口时:默认使用CGLIB进行动态代理的实现。
2.创建的类使用到接口时:默认使用InvocationHandler进行动态代理的实现。

使用接口时,Spring将使用InvocationHandler进行动态代理,而使用InvocationHandler的时候,代理类会实现与被代理类的相同接口,而代理对象与被代理对象属于同层不能像上/下转型,因此报错。
而通过CGLIB成功创建的动态代理,实际是被代理类的一个子类。可以上/下转型。

测试

  @Test
    public void test() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookMapperImpl bookMapper = context.getBean(BookMapperImpl.class);
        bookMapper.delBook(8);
    }

可以看到数据库中的数据并没有删除。数据回滚了。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值