Spring5_02 AOP以及事务操作

目录​​​​​​​

一、什么是AOP

二、底层原理

 三、AOP术语

四、AOP操作(准备)

五、AOP操作

一、AspectJ注解

二、AspectJ配置文件

六、Spring的事务管理

1、事务操作简介

 2、声明式事务管理(注解方式)

1、注解实现

2、参数配置

 2、声明式事务管理(xml方式)

3、声明式事务(完全注解方式)


一、什么是AOP

1、面向切面编程(方面),利用AOP可以对业务逻辑各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

2、通俗描述:不通过该修改源代码方式,在主干功能里面添加新功能


二、底层原理

1、AOP底层使用动态代理

(1)有两种动态情况动态代理

第一种 有接口情况,使用JDK动态代理

*创建接口实现类代理对象,增强类的方法

第二种 没有接口情况,使用CGLIB动态代理

*创建子类的代理对象,增强类的方法

         AOP(JDK动态代理)

1、使用JDK动态代理,使用Proxy类里面的方法创建代理对象

(1)调用newProxyInstance(静态)方法

三个参数:类加载器,增强方法所在类实现的接口,实现这个接口InvocationHandler,创建代理对象,写增强方法

2、编写JDK动态代理代码

(1)创建接口,定义方法


public interface UserDao {
    public int add(int a, int b);
    public String update(String id);
}

(2)创建接口实现类,实现方法

package com.atguigu.spring5;

public class UserDaoImpl implements UserDao {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public String update(String id) {
        return id;
    }
}

(3)使用Proxy类创建接口的代理对象

package com.atguigu.spring5;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class JDKProxy {

    public static void main(String[] args) {
        Class[] interfaces = {UserDao.class};
        //创建接口实现类代理对象
        UserDao userDao = new UserDaoImpl();
        UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
        int add = dao.add(1, 2);
        System.out.println(add);
        String update = dao.update("2007940408");
        System.out.println(update);
    }

}

//创建代理对象代码
class UserDaoProxy implements InvocationHandler{

    //创建的是谁的代理对象,把它传进来便于增强
    //有参构造器
    private Object obj;
    public UserDaoProxy(Object obj) {
        this.obj = obj;
    }

    //增强的逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前
        System.out.println("方法之前执行"+method.getName()+"传递的参数:"+ Arrays.toString(args));
        //被增强的方法执行
        Object res = method.invoke(obj, args);
        //方法之后
        System.out.println("方法之后执行"+obj);
        return res;
    }
}

执行结果如下: 

 三、AOP术语

1、连接点

类里面哪些方法可以被增强,这些方法称为连接点

2、切入点

实际被真正增强的方法

3.通知(增强)

(1)实际增强的逻辑部分称为通知

(2)通知有多种类型

*前置通知 @Before

*后置通知 @After

*环绕通知 @Around

*异常通知 @AfterThrowing

*最终通知 @AfterReturning

4、切面

是动作

(1)把通知应用到切入点过程

四、AOP操作(准备)

1、Spring框架一般基于AspectJ实现AOP操作

(1)什么是AspectJ

*AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring一起用,进行AOP操作

2、基于AspectJ实现AOP操作

(1)基于xml配置文件

(2)基于注解方式(使用)

3、在项目工程里引入AOP相关依赖

 4、切入点表达式

(1)切入点表达式作用:知道对哪个类里的哪个方法进行增强

(2)语法结构:

execution(【权限修饰符】【返回类型】【全类名】【方法名称】【参数列表】)

*权限修饰符可省略,返回值可使用通配符*

举例1:对com.atguigu.dao.BookDao类里面的add进行增强

execution(* com.atguigu.dao.BookDao.add(..))

举例2:对com.atguigu.dao.BookDao类里面的所有方法进行增强

execution(* com.atguigu.dao.BookDao.*(..))

举例2:对com.atguigu.dao.包里面所有类和类里所有方法进行增强

execution(* com.atguigu.dao.*.*(..))

五、AOP操作

一、AspectJ注解

        1、创建类,在类里面定义方法

public class User {
    public void add(){
        System.out.println("add....");
    }
}

 2、创建增强类(编写增强的逻辑)

(1)在增强类里面,创建方法,让不同的方法代表不同通知类型

package com.atguigu.spring5.aopanno;

//增强类
public class UserProxy {

    //前置通知
    public void before(){
        System.out.println("before.....");
    }
}

3、进行通知的配置

(1)在spring配置文件中,开启注解扫描

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

(2)使用注解创建User和UserProxy对象 

(3)在增强类上面添加注解@Aspect

(4)在spring配置文件中开启生成代理对象

<!--    开启AspectJ生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

4、配置不同类型的通知

(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

//增强类
@Component
@Aspect
public class UserProxy {
    //Before表示是前置通知
    @Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void before(){
        System.out.println("before.....");
    }
}

 5、相同的切入点抽取

 //相同切入点的抽取
    @Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void pointCutDemo(){

    }

    //Before表示是前置通知
    @Before(value = "pointCutDemo()")
    public void before(){
        System.out.println("before.....");
    }

6、有多个增强类对同一方法进行增强,设置增强类优先级

(1)在增强类上面添加注解@Order(数字类型值),值越小,优先级越高

//增强类
@Component
@Aspect
@Order(3)
public class UserProxy {

二、AspectJ配置文件

六、Spring的事务管理

1、事务操作简介

①、事务添加到JavaEE三层结构里面的Service层中,理论上也可以加到DAO层

②、Spring中进行事务管理的操作有两种方式:编程式和声明式

③、声明式事务包括xml方式和注解方式

④、在Spring,事务管理底层原理是AOP

⑤、Spring中提供了一个接口PlatformTransactionManager,代表事务管理器,它为不同的框架提供了不同的实现类,红框中时mybatis的实现类

 2、声明式事务管理(注解方式)

1、注解实现

第一步首先创建数据源

第二步 为指定数据源配置事务管理器

第三步开启事务注解

这一步前提是在名称空间中引入事务的名称空间

然后开启事务注解,这里面要用到我们配置的事务管理器

最后在service类上添加事务注解即可实现

注意:

(1)@Transcational,这个注解添加到类上面,也可以添加到方法上面

(2)如果把这个注解添加到类上面,那么类里的所有方法都添加事务

(3)如果把这个注解添加到方法上面,那么为这个方法添加事务

2、参数配置

@Transcational注解中的参数列表如下:

①propagation 事务传播行为

 ②isolation 事务隔离级别

事务有隔离性

 (4)不可重复读,一个未提交事务读取到另一提交事务修改数据

 (5)幻读:一个未提交事务读到另一提交事务添加数据

通过设置事务隔离性可以解决三个读的问题

 mysql默认是可重复读。

③timeout 超时时间

 -1代表不超时

④rollbackFor 回滚

出现那些异常进行事务回滚

⑤noRollbackFor 不回滚

出现那些异常不进行事务回滚

⑥readOnly 是否只读

默认false,可以进行增删改查,而true表示只能进行查询操作

 2、声明式事务管理(xml方式)

在spring配置文件中进行配置

第一步 配置事务管理器

第二步 配置通知

针对accountMoney方法添加事务

第三步 配置切入点和切面

3、声明式事务(完全注解方式)

创建配置类代替xml配置文件

 配置类中写上数据库连接池,完整代码如下

1、创建配置类,使用配置类替代 xml 配置文件
@Configuration //配置类
@ComponentScan(basePackages = "com.atguigu") //组件扫描
@EnableTransactionManagement //开启事务
public class TxConfig {
 //创建数据库连接池
 @Bean
 public DruidDataSource getDruidDataSource() {
     DruidDataSource dataSource = new DruidDataSource();
     dataSource.setDriverClassName("com.mysql.jdbc.Driver");
     dataSource.setUrl("jdbc:mysql:///user_db");
     dataSource.setUsername("root");
     dataSource.setPassword("root");
     return dataSource;
 }
 //创建 JdbcTemplate 对象
 @Bean
 public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
     //到 ioc 容器中根据类型找到 dataSource
     JdbcTemplate jdbcTemplate = new JdbcTemplate();
     //注入 dataSource
     jdbcTemplate.setDataSource(dataSource);
     return jdbcTemplate;
 }
 //创建事务管理器
 @Bean
 public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
     DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
     transactionManager.setDataSource(dataSource);
     return transactionManager;
 }
}

如此以来,即可使得@Transactional注解生效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值