SSM 框架之 Spring AOP, Spring 事务

Spring AOP

一个配置实例:

添加依赖:

	<!-- aspectj依赖, 用于解析切入点表达式-->
	<dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.7</version>
    </dependency>

主配置文件:

<!-- 被代理类-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>

<!-- 切面类注册到 IOC -->
<bean id="logger" class="com.itheima.utils.Logger"></bean>

<!--配置AOP-->
<aop:config>
    <!--配置切面类 -->
    <aop:aspect id="logAdvice" ref="logger">
        <!-- 配置通知的类型,并且建立通知方法和切入点方法的关联-->
        <!-- 配置切入点表达式为全称-->
        <aop:before method="printLog" pointcut="execution(public void     com.itheima.service.AccountServiceImpl())"></aop:before>
    </aop:aspect>
</aop:config>

切面类(提供增强方法的类) :

public class Logger {
    public void printLog(){
        System.out.println("Logger类中的pringLog方法开始记录日志了。。。");
    }
}

切入点表达式的写法:

全通配写法: * *..*.*(..)
实际开发中, 使用 切到service层所有实现类的所有方法, 比如: * com.zzy.service.impl.*.*(..)

环绕通知, 以及单独为切入点表达式配置的标签

注意: <aop:pointcut 标签要么在 <aop:aspect 内部, 表示此 切入点表达式只适用于这个切面, 或者此标签在<aop:aspect 之前的同级标签, 表示此 切入点表达式通用

<!--配置AOP-->
    <aop:config>
        <!-- 配置切入点表达式 id属性用于指定表达式的唯一标识。expression属性用于指定表达式内容
              此标签写在aop:aspect标签内部只能当前切面使用。
              它还可以写在aop:aspect外面,此时就变成了所有切面可用
          -->
        <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*                        (..))"></aop:pointcut>
        <!--配置切面 -->
        <aop:aspect id="logAdvice" ref="logger"></aop:aspect>
            <!-- 配置环绕通知 详细的注释请看Logger类中-->
            <aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around>
        </aop:aspect>
    </aop:config>

切面类:

public class Logger{
    // 环绕通知
    public Object aroundPringLog(ProceedingJoinPoint pjp){
        Object rtValue = null;
        try{
            Object[] args = pjp.getArgs();//得到方法执行所需的参数
            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。前置");
            rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)
            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。后置");
            return rtValue;
        }catch (Throwable t){
            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。异常");
            throw new RuntimeException(t);
        }finally {
            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终");
        }
    }
}

使用注解替代aop的 xml配置

主配置文件:

<!-- 配置spring开启注解AOP的支持 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>	

或者采用全注解方式, @EnableAspectJAutoProxy 替代上面的 aop自动代理配置

@Configuration	//主配置
@Import(JdbcConfig.class)	//引入的配置
@ComponentScan(basePackages = {"com.zzy"})
@EnableAspectJAutoProxy 	//aop代理自动开启
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {

}

切面类:

@Component("logger")
@Aspect//表示当前类是一个切面类
public class Logger{
	// 配置切入点表达式, 仅适用本切面
	@Pointcut("execution(* com.itheima.service.impl.*.*(..))")
    private void pt1(){}
    
    // 环绕通知, 指定切入点表达式
    @Around("pt1()")
    public Object aroundPringLog(ProceedingJoinPoint pjp){
        Object rtValue = null;
        try{
            Object[] args = pjp.getArgs();//得到方法执行所需的参数
            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。前置");
            rtValue = pjp.proceed(args);//明确调用业务层方法(切入点方法)
            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。后置");
            return rtValue;
        }catch (Throwable t){
            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。异常");
            throw new RuntimeException(t);
        }finally {
            System.out.println("Logger类中的aroundPringLog方法开始记录日志了。。。最终");
        }
    }
}

Spring 事务

demo地址 事务的动态代理

AOP结合自定义事务管理器(手写)

package com.itheima.utils;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
 */
@Component("txManager")
@Aspect
public class TransactionManager {

    @Autowired
    private ConnectionUtils connectionUtils;

    @Pointcut("execution(* com.itheima.service.impl.*.*(..))")
    private void pt1(){}

    /**
     * 开启事务
     */
    public  void beginTransaction(){
        try {
            connectionUtils.getThreadConnection().setAutoCommit(false);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 提交事务
     */
    public  void commit(){
        try {
            connectionUtils.getThreadConnection().commit();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 回滚事务
     */
    public  void rollback(){
        try {
            connectionUtils.getThreadConnection().rollback();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 释放连接
     */
    public  void release(){
        try {
            connectionUtils.getThreadConnection().close();//还回连接池中
            connectionUtils.removeConnection();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Around("pt1()")
    public Object aroundAdvice(ProceedingJoinPoint pjp){
        Object rtValue = null;
        try {
            //1.获取参数
            Object[] args = pjp.getArgs();
            //2.开启事务
            this.beginTransaction();
            //3.执行方法
            rtValue = pjp.proceed(args);
            //4.提交事务
            this.commit();
            //返回结果
            return  rtValue;
        }catch (Throwable e){
            //5.回滚事务
            this.rollback();
            throw new RuntimeException(e);
        }finally {
            //6.释放资源
            this.release();
        }
    }
}

基于xml 的声明式事务

标签关系: <aop:config 包含 <aop advisor 依赖 <tx:advice 依赖 txManager bean 依赖注入 DataSource bean

<!-- 配置aop-->
    <aop:config>
        <!-- 配置切入点表达式-->
        <aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut>
        <!--建立切入点表达式和事务通知的对应关系 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
    </aop:config>

    <!-- 配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 配置事务的属性
        isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
        propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
        read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
        timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
        rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
        no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。
        -->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" read-only="false"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

注意: <tx:method 标签内定义了 txManager所管理的方法的命名规范

使用注解配置事务管理器

使用 <tx:annotation-driven transaction-manager=“transactionManager”/> 开启 spring对注解事务的支持, 或者在全注解配置下, 添加 @EnableTransactionManagement

用@Transactional 注解标记方法或类, 即可代替上面的 <aop:config 和 <tx:advice

注意: spring 声明式事务的两种配置方法, 采用xml 则只需遵循方法命名规范, 采用注解, 需要逐个类地配置@Transactional

发布了15 篇原创文章 · 获赞 3 · 访问量 550
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览