Spring3

1、AOP概述

AOP为Aspect Orientend Programming 的缩写,意为 :面向切面编程,通过预编译方式运行期间动态代理实现程序功能的统一维护的一种技术。

AOP是OOP的延续,是软件开发中的一个热点,也是Spring 框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使地业务逻辑各部分之间的耦合度降低提高程序的可重用性,同时提高了开发的效率
AOP OOP在字面上虽然非常类似,但却是不同领域的两种设计思想。
OOP(面向对象编程),针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更高清晰高效的逻辑单元划分。
AOP针对业务处理过程中的切面进行提取,他所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。
面向切面编程好处:
减少重复,专注业务

注意:面向切面编程只是面向对象编程的一种补充
核心原理:
使用动态代理的方式在执行方法前后或者出现异常的时候加入相关的逻辑。
eg:
事务处理:开启事务,关闭事务,出现异常后回滚事务
权限判断:在执行方法前,判断是否具有权限
日志:在执行前进行日志处理
在这里插入图片描述

2、AOP的基本概念

连接点(Joinpoint) :类中可以被增强的方法,这个方法就称为连接点
切入点(pointcut):类中有很多方法可以被增强,但实际中只有add和update被增加了,那么add和update 方法就被称为切入点(实际实现的连接点)
通知(Advice):通知是指一个切面在特定的连接点要做的事情(增强的功能)。通知分为方法执行前通知,方法执行后通知,环绕通知。
切面(Aspect):把通知添加到切入点的过程叫切面
目标(Target):代理的目标对象(要增强的类)
代理(Proxy):向目标对象应用通知之后创建的代理对象

3、springAOP实现

对于AOP这种编程思想,很多框架都进行了实现。Spring就是其中之一,可以完成切面编程。
AspectJ也实现了AOP功能,AspectJ是一个基于Java语言的AOP框架,他提供了强大的AOP功能且实现方式更为简洁方便,而且还支持注解式开发。所以,Spring 又将AspectJ的对于AOP的实现也引入到了自己的框架中。
在Spring 中使用AOP开发时,一般使用AspectJ的实现方式。
AspectJ是一个优秀面向切面的框架,他扩展了Java语言,提供了强大的切面实现。
AspectJ中常用的通知有五种类型:
前置通知 ,后置通知 ,环绕通知 , 异常通知 , 最终通知

1、下载相关jar

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>

2、基于aspectJ的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"
        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/context
        http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="aopdemo" class="com.ffyc.spring.aop.AopDemo"></bean>

    <aop:config>
    <!--配置切入点-->
        <aop:pointcut id="savedao" expression="execution(* com.ffyc.spring.dao.UserDao.savedao(..))"/>
	<!--配置通知和切入点-->
        <aop:aspect ref="aopdemo">
       <!-- <aop:before method="saveLog" pointcut-ref="savedao"></aop:before>
            <aop:after method="saveLog" pointcut-ref="savedao"></aop:after>
            <aop:after-throwing method="exceptionAdice" pointcut-ref="savedao" throwing="e"></aop:after-throwing>-->
          <aop:around method="aroundAdice" pointcut-ref="savedao"></aop:around>
        </aop:aspect>
    </aop:config>

</beans>

在这里插入图片描述
在spring.xml中添加配置,启动AspectJ支持:

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

3、实现通知

环绕通知

    @Around("execution(* com.ffyc.spring.dao.UserDao.savedao())")
    public  void aroundAdice(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("前置方法");
        try {
            proceedingJoinPoint.proceed();
        }catch (Throwable e){
            System.out.println(e.getMessage());
        }
        System.out.println("后置方法");
    }

在这里插入图片描述
前置通知

    @Before("execution(* com.ffyc.spring.dao.UserDao.savedao())")

在这里插入图片描述
后置通知

  @After("execution(* com.ffyc.spring.dao.UserDao.savedao())")

在这里插入图片描述
异常通知

    @AfterThrowing(value = "execution(* com.ffyc.spring.dao.UserDao.savedao())",throwing = "e")
    public void exceptionAdice(Throwable e){

        System.out.println(e.getMessage());
    }

在这里插入图片描述
最终通知

@AfterReturning("execution(* com.ffyc.spring.dao.UserDao.savedao())")

UserDao

@Repository(value = "userDao")
public class UserDao{
    @Autowired
     JdbcTemplate jdbcTemplate;

    public void savedao(){
        System.out.println("保存dao方法");
    }
    public void deletedao(){
        System.out.println("删除");
    }
}

4、Spring事务管理

事务可以看做是由数据库若干操作组成的一个单元
事务的作用:保证用户的每一个操作都是可靠的,事务的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些操作要么都完成,要么都取消,保证数据满足一致性的要求
Spring中的事务管理分为两种形式:编程式事务;声明式事务
**编程式事务:**在项目中很少使用,这种方式需要注入一个事务管理对象TransactionTemplate,然后在我们代码中需要提交事务或回滚事务时自己写代码实现。

**声明式事务:**管理建立在AOP基础上,本质是对方法前后进行拦截,所以声明式事务是方法级别的。
Spring声明式事务管理方式有两种:
基于xml配置
基于注解实现

Spring 事务管理API
PlatformTransactionManager 事物管理器接口
Spring 针对不同的 dao 框架,提供了不同的实现类,Jdbc,mybatis 事物管理实
现类是 DataSourceTransactionManager.

1、配置事务管理器

 <!--数据库事务:是对数据库若干操作组成的一个单元(整体)
    在我们的一次save时,里面包含了两个或者更多个对数据库的操作,
    那么我们认为着若干操作,应该是一个单元(整体),
    这就是事务的原子性(不可分割性),多个操作要么执行成功,要么都不执行成功。
    -->
    <!-- 配置 spring 事务管理类, 并注入数据源 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"></property>
    </bean>

2、XML配置方式


    <tx:advice id="txadvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="savedao" expression="execution(* com.ffyc.spring.dao.UserDao.savedao(..))"/>
        <aop:advisor advice-ref="txadvice" pointcut-ref="savedao"/>
    </aop:config>

3、注解方式

&lt;!&ndash; 开启注解事务管理 &ndash;&gt;
    <tx:annotation-driven transaction-manager="transactionManager"/>

4、例子

eg:

@Repository(value = "userDao")
public class UserDao{
    @Autowired
     JdbcTemplate jdbcTemplate;

    @Transactional
    public void savedao(){
        jdbcTemplate.update("insert into admin(account,password,sex)values (?,?,?)","122","222","男");
       int s=10/0;
        jdbcTemplate.update("insert into admin(account,password,sex)values (?,?,?)","122","222","女");
    }
    public void deletedao(){
        System.out.println("删除");
    }

在这里插入图片描述
如果去掉 int s=10/0; 不会出现异常,则运行成功,且数据插入数据库中
在这里插入图片描述
在这里插入图片描述

5、Spring事务传播行为

什么叫事务传播行为?

传播,至少有两个东西,才能发生传播。单体不存在传播行为。事务传播行为(propagation behavior) 指的就是当一个事务方法被另一个事务方法调用时,这个事务应该如何进行。事务传播行为是Spring 框架独有的事务增强特性,他不属于事务实际提供数据库行为。

Spring定义了七种传播行为:

1、 PROPAGATION_REQUIRED

Propagation.REQUIRED A 和 B 都为REQUIRED ,A调用B方法,那么B事务加入到A事务中执行 A 无事务,调用B方法,传播行为为REQUIRED,B会自己开启一个事务

eg:事务A

@Service(value = "deptService")
public class DeptService {
  @Autowired
    DeptDao deptDao;
  @Autowired
  CommonService commonService;
    @Transactional(propagation = Propagation.REQUIRED)
    public void save(){
        deptDao.save();
        commonService.saveLog();
        //int s=10/0;
    }
}

事务B

@Service(value = "commonService")
public class CommonService {

    @Autowired
    CommonDao commonDao;
    public void saveLog(){
        commonDao.saveLog();
    }
}    

在这里插入图片描述

2、 PROPAGATION_SUPPORTS
   /*
    Propagation.SUPPORTS A 传播行为为REQUIRED  ,B传播行为为SUPPORTS ,那么B加入到A中执行
                            A无事务,B也就无事务
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void saveLog(){
        commonDao.saveLog();
        int s=10/0;
    }

在这里插入图片描述

3、 PROPAGATION_REQUIRES_NEW
    /*
    Propagation.REQUIRES_NEW  B传播事务为Propagation.REQUIRES_NEW,B方法会开启一个独立的新事务,B不会受到A的影响
                                A 没有事务,B传播事务为_new ,B方法会开启一个独立的新事务
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveLog(){
        commonDao.saveLog();
    }

在这里插入图片描述

4、 PROPAGATION_MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常

5、 PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务
挂起

6、PROPAGATION_NEVER

以非事务方式执行,如果当前存在事务,则抛出异常

7、PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事
务,则执行与 PROPAGATION_REQUIRED 类似的操作

声明式事务不生效的场景

@Transactional应用在非public修饰的方法上
@Transactional注解属性propagation设置错误
同一个类中方法调用,导致@Transactional失效
异常被catch捕获导致@Transactional失效
数据库引擎不支持事务

6、Spring集成Mybatis

Spring集成Mybatis其核心是将SqlSessionFactory 交由Spring管理,并由Spring管理对dao接口的代理实现。

1、导入mybatis jar包

   <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.2</version>
        </dependency>

2、导入 Spring - mybatis jar包

     <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.1</version>
        </dependency>

3、配置 sqlSessionFactory

<!--配置 sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="druidDataSource"></property>
        <property name="configLocation" value="classpath:mybatis_config.xml"></property>
        <property name="mapperLocations" value="classpath:mapper/*Mapper.xml"></property>
    </bean>

4、指定生成接口代理

    <!--接口代理-->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.ffyc.ssm.dao"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

5、在service 中注入Dao代理接口,此接口有Sping代理实现

   @Autowired
    AdminDao adminDao;

eg:
CommonResult

package com.ffyc.ssm.common;

/**
 *  结果封装类
 */
public class CommonResult<T> {

      private Integer code;
      private String msg;
      private T data;

    public CommonResult(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

Controller

@Controller
@RequestMapping(path = "/admin")
public class AdminController{
    @Autowired
    AdminService adminService;
    @PostMapping(path = "/getAdmin")
    public void getAdmin(Admin admin, Integer flag){
        System.out.println("admin:"+admin.toString());
    }
}

dao

public interface AdminDao {
   void saveAdmin();
}

modle

package com.ffyc.ssm.modle;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class Admin {
    private  Integer id;
    private  String account;
    private  String password;
    private  String  sex;
    @DateTimeFormat(pattern = "YYYY-MM-dd")
    private Date birthday;

    private  String oldFileName;
    private  String newFileName;

    public String getOldFileName() {
        return oldFileName;
    }

    public void setOldFileName(String oldFileName) {
        this.oldFileName = oldFileName;
    }

    public String getNewFileName() {
        return newFileName;
    }

    public void setNewFileName(String newFileName) {
        this.newFileName = newFileName;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

service

@Service
public class AdminService {
    @Autowired
    AdminDao adminDao;
    @Transactional
    public void  saveAdmin(){
        adminDao.saveAdmin();
    }
}

mapper

<mapper namespace="com.ffyc.ssm.dao.AdminDao">
   <insert id="saveAdmin">
         insert into admin(account,password)values('123','123')
      </insert>
</mapper>

需要配置这些xml
在这里插入图片描述
html

  <a href="admin/getAdmin?id=1&name='zhangsan'">admin</a>

  <form method="post" action="admin/getAdmin">
       <input type="text" name="account">
       <input type="text" name="password">
       <input type="text" name="sex">
       <input type="text" name="birthday">
       <input type="submit">
  </form>

在这里插入图片描述
如果所有格式都正确会响应回来:
在这里插入图片描述
不正确格式,则会响应:
在这里插入图片描述

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值