Spring

一、 MVC三层架构

在这里插入图片描述

Model

  • 业务处理:业务逻辑(Service)
  • 数据持久层:CRUD(Dao)

View

  • 展示数据
  • 提供链接发起Service请求(a、form、img…)

Controller

  • 接收用户的请求(req:请求参数、Session信息)
  • 交给业务层处理对应的代码
  • 控制视图的跳转

登陆---->接受用户登陆请求---->处理用户请求(获取用户登陆参数:username、password)---->交给业务层处理登陆业务(判断用户名是否正确)---->Dao层查询用户名和密码是否正确---->数据库

过滤器(Filter)

在这里插入图片描述
步骤:

  1. maven导包
  2. 实现javax.servlet的Filter接口,重新特定方法
  3. 配置web.xml

注意:
1.过滤中的所有代吗,在过滤特定请求的时候都会执行
2、必须要让过滤器继续通行
chain.doFilter(request,response);

案例:设置两条路径,/filter/hello_filter以及/hello_filter,通过过滤器实现/filter/*的路径设置编码格式。最终显示:/filter/hello_filter正常输出中文格式的“你好世界!”,/hello_filter输出乱码

//展示类
public class FilterServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("<h1>世界,你好!</h1>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

Filter类,注意导包Filter为javax.servlet包下的Filter

public class FilterTest implements Filter {
	//初始化在系统启动时就加载
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter init");
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    	//设置编码格式操作
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");

        System.out.println("Filter doFilter Before");
        //正确执行过滤器,必须加此行,不然会一直卡死不往下执行
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("Filter doFilter After");
    }
	//销毁在系统关闭时销毁
    public void destroy() {
        System.out.println("Filter destroy");
    }
}

web.xml,配置servlet和filter:
/filter/hello_filter和/hello_filter都可以进入展示类
filter配置地址前缀为/filter的才可进入

    <servlet>
        <servlet-name>FilterIndex</servlet-name>
        <servlet-class>com.zzz.filter.FilterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FilterIndex</servlet-name>
        <url-pattern>/filter/hello_filter</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>FilterIndex</servlet-name>
        <url-pattern>/hello_filter</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>FilterTest</filter-name>
        <filter-class>com.zzz.filter.FilterTest</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterTest</filter-name>
        <url-pattern>/filter/*</url-pattern>
    </filter-mapping>

JDBC复习

常用接口

(1) Driver 接口:加载驱动程序。
(2) DriverManager:装人所需的 JDBC 驱动程序,编程时调用它的方法来创建连接。
(3) Connection 接口:编程时使用该类对象创建 Statement 对象。
(4) Statement 接口:编程时使用该类对象得到 ResultSet 对象。
(5) ResultSet:负责保存 Statement 执行后所产生的查询结果。

连接数据库

  1. 提前创建好数据库
CREATE DATABASE db1;
 
USE db1;
 
CREATE TABLE `user`(
	`id` INT,
	`name` VARCHAR(30)
);
 
INSERT INTO `user` VALUES (1,'张一'),(2,'张二'),(3,'张三'),(4,'张四'),(5,'张五');
  1. 导包

  1. 连接Mysql
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
Connection com = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "123456");
Statement stat = com.createStatement();

// 执行 增删改查 (DML)语句用 int executeUpdate(Sting sql);
 // 执行 DQL 语句 ResultSet executeQuery(String sql);
String sql = "SELECT * FROM user";
ResultSet rs = stat.executeQuery(sql);

while (rs.next()){
        System.out.println(rs.getInt("id") + "\t" + rs.getString("name"));
}
 stat.close();
 com.close();

JDBC 预编译

JDBC事务

  1. 开启事务 void setAutoCommit(boolean autoCommit)
  2. 提交事务 void commit() 使自上次提交/回滚以来所做的所有更改为永久更改,并释放此Connection对象当前持有的所有数据库锁。
  3. 回滚事务 void rollback() 撤销当前事务中所做的更改,并释放此Connection对象当前持有的所有数据库锁
try{
connection.setAutoCommit(false);//设置为false,开启事务
...sql语句

connection.commit();//以上两条SQL都执行成功就提交事务。
}catch(){
connection.rollback();
}

二、Spring

1、优点

  • Spring是一个轻量级的框架 , 非侵入式的 (不会破坏原有程序,甚至简化原有代码)
  • 控制反转 IoC , 面向切面 Aop
  • 支持 事务

一句话概括:Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。

2、IOC

参考:

https://blog.csdn.net/weixin_45842494/article/details/122772824?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171930621116800227431608%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171930621116800227431608&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-12-122772824-null-null.nonecase&utm_term=Spring学习笔记&spm=1018.2226.3001.4450

3、applicationContext

https://blog.csdn.net/weixin_45842494/article/details/122772913?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171930621116800227431608%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171930621116800227431608&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-11-122772913-null-null.nonecase&utm_term=Spring%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0&spm=1018.2226.3001.4450

4、依赖注入(DI)

https://blog.csdn.net/weixin_45842494/article/details/122775544?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171930621116800227431608%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171930621116800227431608&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-9-122775544-null-null.nonecase&utm_term=Spring%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0&spm=1018.2226.3001.4450

5、Bean的作用域

https://blog.csdn.net/weixin_45842494/article/details/122776494?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171930621116800227431608%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171930621116800227431608&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-8-122776494-null-null.nonecase&utm_term=Spring%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0&spm=1018.2226.3001.4450

6、Spring自动装配

在这里插入图片描述

https://blog.csdn.net/weixin_45842494/article/details/122777536?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171930621116800227431608%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171930621116800227431608&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-7-122777536-null-null.nonecase&utm_term=Spring%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0&spm=1018.2226.3001.4450

7. Spring使用注解开发

在这里插入图片描述

https://blog.csdn.net/weixin_45842494/article/details/122778659?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171930621116800227431608%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=171930621116800227431608&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~times_rank-6-122778659-null-null.nonecase&utm_term=Spring%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0&spm=1018.2226.3001.4450

@Component的三个衍生注解

我们这些注解,就是替代了在配置文件当中配置步骤而已!更加的方便快捷!

@Component三个衍生注解

为了更好的进行分层,Spring可以使用其它三个注解,目前使用哪一个功能都一样。

  • @Controller:web层
  • @Service:service层
  • @Repository:dao层
    以上这些注解,功能一样,就相当于将这个类交给Spring管理装配了!

前面写了指定注解扫描包

<context:component-scan base-package="com.xxc.pojo"/>

那如果使用了衍生注解,这些注解所在类并不完全在pojo下,这个时候,我们可以扩大指定注解扫描包的作用范围。

<context:component-scan base-package="com.xxc"/>

8、基于Java类进行配置

  1. 在User类上添加@Component注解,表示这个类标注为Spring的一个组件,放到容器中
  2. 新建一个config配置包,编写一个MyConfig配置类
    • @Configuration 注解,代表这是一个配置类。
    • 同时在user方法上注册@Bean
    • 这个方法的返回值就是Bean的class,方法名就是bean的id。
@Configuration  // 代表这是一个配置类
public class MyConfig {

    @Bean  // 注册一个bean,这里的返回值就是Bean的类型,方法名就是bean的id。
    public User user(){
        return new User();
    }
}
  1. 测试
    这里需要new AnnotationConfigApplicationContext。之前都是CPX。这里用获取注解的Context。
    getBean(“user”, User.class)其实就是获取方法名
public class MyTest {
    @Test
    public void test(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        User user = applicationContext.getBean("user", User.class);
        System.out.println(user.getName());
    }
}

9、代理模式

AOP的底层机制就是动态代理模式

分类:

  • 静态代理
  • 动态代理

在这里插入图片描述

静态代理

静态代理代理的是真实对象

静态代理角色分析

  • 抽象角色 : 一般使用接口或者抽象类来实现
  • 真实角色 : 被代理的角色
  • 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作
  • 客户 : 使用代理角色来进行一些操作

代码实现

Rent.java 租房。即抽象角色

// 抽象角色,租房
public interface Rent {
    public void rent();
}

Host.java 房东。真实角色

//真实角色: 房东,房东要出租房子
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

Proxy.java 代理角色。内置private Host host;房东属性

//代理角色:中介
public class Proxy implements Rent {
    private Host host; // 中介代理的是房东,将房东作为属性

    public Proxy() {}

    public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        seeHouse();
        host.rent();
        fare();
    }

    // 看房
    public void seeHouse(){
        System.out.println("带客户看房子。");
    }

    // 收中介费
    public void fare(){
        System.out.println("收中介费");
    }
}

Client.java 客户

public class Client {
    public static void main(String[] args) {
        // 房东要出租房
        Host host = new Host();
        // 中介帮助房东
        Proxy proxy = new Proxy(host);

        // 客户找中介
        proxy.rent();
    }
}

结果:
在这里插入图片描述

分析:在这个过程中,你直接接触的是中介,但是你依然通过中介租到了房东的房子。这就是所谓的代理模式。对于房东来说很纯粹,只有租出房子,而中介可以附加一些额外的操作,比如带客户看房,收中介费等等。

静态代理的优缺点

优点

  • 可以使得我们的真实角色更加纯粹,不再去关注一些公共的事情。
  • 公共的业务由代理来完成,实现了业务的分工。
  • 公共业务发生扩展时变得更加集中和方便。

缺点

  • 一个真实的角色就会产生一个代理角色;代码量翻倍,开发效率低
  • 我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !

静态代理再理解

  1. 创建一个抽象角色,增删改查!
//抽象角色:增删改查业务
public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}

  1. 我们需要一个真实对象来完成这些增删改查操作
//真实对象,完成增删改查操作的人
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("add了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("delete了一个用户");
    }

    @Override
    public void update() {
        System.out.println("update了一个用户");
    }

    @Override
    public void query() {
        System.out.println("query了一个用户");
    }
}

  1. 需求来了,现在我们需要增加一个日志功能,怎么实现?
  • 思路1 :在实现类上增加代码 【麻烦!】
  • 思路2:使用代理来做,能够不改变原来的业务情况下,实现此功能就是最好的了!
  1. 设置一个代理类来处理日志! 代理角色
//代理角色,在这里面增加日志的实现
public class UserServiceProxy implements UserService {
    private 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 str){
        System.out.println("打印了"+str+"的日志");
    }
}

  1. 测试访问类:
    运用代理模式,新建一个类,实现接口,代理真实对象。
    这里使用setUserService使用了控制反转的思想,将调用权给用户。
public class Client {
    public static void main(String[] args) {
        //真实业务
        UserServiceImpl userService = new UserServiceImpl();
        //代理类
        UserServiceProxy proxy = new UserServiceProxy();
        //使用代理类实现日志功能!
        proxy.setUserService(userService);
        proxy.add();
        proxy.delete();
        proxy.update();
        proxy.query();
    }
}

我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想。
在这里插入图片描述

动态代理

底层是反射
代理的是接口(静态代理代理的是真实对象)

  • 动态代理的角色和静态代理的一样。
  • 动态代理的代理类是动态生成的,静态代理的代理类是我们提前写好的
  • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
    • 基于接口的动态代理----JDK动态代理
    • 基于类的动态代理–cglib
    • 现在用的比较多的是 javasist 来生成动态代理
    • 我们这里使用JDK的原生代码来实现,其余的道理都是一样的!

JDK的动态代理需要了解两个类
nvocationHandler (调用处理程序)和 Proxy(动态创建代理对象)

代码实现

抽象角色和真实角色与之前的一样!

//抽象角色:租房
public interface Rent {
    public void rent();
}

//真实角色: 房东,房东要出租房子
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

ProxyInvocationHandler.java代理角色

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);
    }

    // proxy : 代理类 method : 代理类的调用处理程序的方法对象.
    // 处理代理实例上的方法调用并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }
    // 看房
    public void seeHouse(){
        System.out.println("带房客看房");
    }
    // 收中介费
    public void fare(){
        System.out.println("收中介费");
    }
}

Client.java

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.rent();
    }
}

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

动态代理深化理解

我们来使用动态代理实现代理我们后面写的UserService!
我们也可以编写一个通用的动态代理实现的类(相当于工具类)!所有的代理对象设置为Object即可!

ProxyInvocationHandler .java
//此时有需求:添加日志

public class ProxyInvocationHandler implements InvocationHandler {

    private Object object;

    public void setObject(Object object) {
        this.object = object;
    }

    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object invoke = method.invoke(object, args);
        return invoke;
    }

    //此时有需求:添加日志
    public void log(String str){
        System.out.println("执行了"+str+"方法");
    }

}

Client.java

public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        proxyInvocationHandler.setObject(userService);
        UserService proxy = (UserService) proxyInvocationHandler.getProxy();
        proxy.add();
    }
}

动态代理的好处

静态代理有的它都有,静态代理没有的,它也有!

  • 可以使得我们的真实角色更加纯粹,不再去关注一些公共的事情 .
  • 公共的业务由代理来完成,实现了业务的分工 ,
  • 公共业务发生扩展时变得更加集中和方便 .
  • 一个动态代理 , 一般代理某一类业务
  • 一个动态代理可以代理多个类,代理的是接口!

10、AOP

在这里插入图片描述

使用Spring实现AOP

  1. 通过 Spring API 实现

实现接口MethodBeforeAdvice (前置)、AfterReturningAdvice (后置)。最后去spring的文件中注册 , 并实现aop切入实现 , 注意导入约束

public class BeforeLog implements MethodBeforeAdvice {
    //method : 要执行的目标对象的方法
    //objects : 被调用的方法的参数
    //Object : 目标对象
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注册bean-->
    <bean id="userService" class="com.xxc.service.UserServiceImpl"/>
    <bean id="after" class="com.xxc.log.AfterLog"/>
    <bean id="before" class="com.xxc.log.BeforeLog"/>

    <!--aop的配置-->
    <aop:config>
        <!--切入点 expression:表达式匹配要执行的方法-->
        <aop:pointcut id="pointcut" expression="execution(* com.xxc.service.UserServiceImpl.*(..))"/>
        <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
        <aop:advisor advice-ref="before" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="after" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

  1. 自定义类来实现

自定义一个类,并在配置文件中配置

public class DiyPointcut {
    public void before(){
        System.out.println("============在方法执行前执行=============");
    }
    public void after(){
        System.out.println("===========在方法执行后执行==============");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
	<!--第二种方式自定义实现-->
    <!--注册bean-->
    <bean id="userService" class="com.xxc.service.UserServiceImpl"/>
    <bean id="diy" class="com.xxc.config.DiyPointcut"/>
    <aop:config>
        <aop:aspect ref="diy">
            <aop:pointcut id="diyPonitcut" expression="execution(* com.xxc.service.UserServiceImpl.*(..))"/>
            <aop:before pointcut-ref="diyPonitcut" method="before"/>
            <aop:after pointcut-ref="diyPonitcut" method="after"/>
        </aop:aspect>
    </aop:config>

</beans>

  1. 使用注解实现

编写一个注解实现的增强类,标注@Aspect、@Before(“execution(* com.xxc.service.UserServiceImpl.*(…))”)、@After、 @Around。最后配置文件中配置

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AnnotationPointcut {
    @Before("execution(* com.xxc.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("---------方法执行前---------");
    }
    @After("execution(* com.xxc.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("---------方法执行后---------");
    }
    @Around("execution(* com.xxc.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前");
        System.out.println("签名:"+jp.getSignature());
        //执行目标方法proceed
        Object proceed = jp.proceed();
        System.out.println("环绕后");
        System.out.println(proceed);
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--第三种方式:注解实现-->
    <bean id="userService" class="com.xxc.service.UserServiceImpl"/>
    <bean id="annotationPointcut" class="com.xxc.config.AnnotationPointcut"/>
    <aop:aspectj-autoproxy/>
</beans>

11、整合Mybatis

https://blog.csdn.net/weixin_45842494/article/details/122793998

12、声明式事务

AOP,交给容器管理

当执行一段代码:先新增一条数据,再删除另一条数据,最后查询所有数据,此时删除中代码写错了。

如果没有事务则会出现报错提示,数据新增成功,删除失败。是有问题的,应该保证ACID原则,要么都成功要么都失败。

以前的事务都是手动开启、手动提交的,非常麻烦。
现在Spring给我们提供了事务管理,我们只需要配置即可

声明式事务的配置:

  1. 头文件导入tx:
xmlns:tx="http://www.springframework.org/schema/tx"

http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd

  1. 配置事务
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

  1. 配置事务通知
    在开发中,我们只需要配置最后的<tx:method name=“*” propagation=“REQUIRED”/>即可,这个就表示给所有方法添加了事务。
<!--配置事务通知-->
<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>

  1. 配置aop织入
<!--配置aop织入事务-->
<aop:config>
    <aop:pointcut id="txPointcut" expression="execution(* com.xxc.dao.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>

此时的结果: 还是会报异常,但是数据并没有插入,达到了我们想要的效果。

还有一种编程式事务,其原理就是加上trycatch,报错调用回滚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值