springboot开发的常用组件总结-切面组件

AOP(面向切面编程)是Spring框架中的一个重要特性,它允许开发者将横切关注点(如日志、事务管理等)与业务逻辑代码分离,从而提高代码的可维护性和可重用性。在Spring中,AOP通常通过注解来实现,这些注解使得AOP的使用变得更加简单和直观。

常用的AOP注解

@Aspect:用于声明一个类为切面类。

@Component(或@Service、@Repository等):切面类通常也需要被Spring容器管理,因此也需要使用这些注解之一。

@Before:在目标方法执行之前执行。

@After:在目标方法执行之后执行(无论方法执行是否成功)。

@AfterReturning:在目标方法成功执行之后执行(方法出现异常不会执行)。

@AfterThrowing:在目标方法抛出异常时执行。

@Around:在目标方法执行前后执行,并且可以决定是否继续执行目标方法或中断执行。

@Pointcut:用于定义切入点表达式,用于指定哪些方法需要被增强。

Demo
以下是一个简单的AOP示例,演示了如何使用这些注解来记录方法执行的时间。

首先,定义一个切面类LoggingAspect,并使用@Aspect注解标记它:

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // 定义一个切入点表达式,匹配所有com.example.service包下的所有类的所有方法
    @Pointcut("execution(* com.example.service..*.*(..))")
    public void serviceLayerExecution() {}

    // 环绕通知,用于记录方法执行时间
    @Around("serviceLayerExecution()")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object proceed = joinPoint.proceed(); // 继续执行目标方法
        long executionTime = System.currentTimeMillis() - startTime;

        System.out.println("Execution of " + joinPoint.getSignature() + " took " + executionTime + " ms");

        return proceed;
    }
}

然后,在Spring配置中启用AspectJ自动代理(如果你使用的是基于Java的配置,可以在配置类上添加@EnableAspectJAutoProxy注解):

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
    // 配置类内容
}

最后,创建一个服务类ExampleService,并编写一些业务逻辑方法,这些方法将自动被LoggingAspect中定义的环绕通知所增强:

package com.example.service;

public class ExampleService {

    public void doSomething() {
        // 模拟业务逻辑
        try {
            Thread.sleep(1000); // 休眠1秒以模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

当ExampleService中的方法被调用时,LoggingAspect中的环绕通知将执行,并打印出方法执行所需的时间。

请注意,为了简化示例,上述代码省略了Spring容器的配置和启动代码。在实际应用中,你需要确保Spring容器已经正确配置并启动了。

@Transactional

@Transactional 是 Spring
框架提供的一个非常强大的注解,用于声明事务管理的方法边界。当在方法或类上使用该注解时,Spring
会为该方法或类中所有的公共方法创建一个代理,以便在方法执行前后添加事务管理的逻辑。这包括开始事务、提交事务或回滚事务。

主要特点

声明式事务管理:通过注解的方式声明事务的边界,无需编写额外的事务管理代码。

回滚策略:可以指定在遇到哪些异常时回滚事务(默认是运行时异常和错误)。

传播行为:可以控制事务的传播行为,例如当前存在事务时,是加入当前事务还是创建新事务。

隔离级别:可以设置事务的隔离级别,以防止脏读、不可重复读等问题。

超时设置:可以指定事务的超时时间,以秒为单位。

只读标志:可以将事务标记为只读,以提高查询性能(数据库可以根据只读标志进行优化)。

示例 Demo

以下是一个使用 @Transactional 注解的简单示例。假设我们有一个 UserService 类,该类中有一个方法用于保存用户信息。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository; // 假设这是一个数据访问层组件

    @Transactional
    public void saveUser(User user) {
        // 假设这里有一些业务逻辑
        // ...

        // 调用数据访问层保存用户
        userRepository.save(user);

        // 模拟一个运行时异常
        // throw new RuntimeException("保存用户时出错");
    }
}

在这个例子中,saveUser 方法被 @Transactional 注解标记,表示该方法执行时会启动一个新的事务(或者如果当前已经存在事务,则根据传播行为决定是否加入当前事务)。如果在 saveUser 方法执行过程中抛出了运行时异常(默认情况下,运行时异常和错误会导致事务回滚),则 Spring 会自动回滚事务,以确保数据的一致性。

如果你想要自定义事务的回滚策略,比如只在遇到特定类型的异常时才回滚事务,可以使用 @Transactional 注解的 rollbackFor 属性。例如:

@Transactional(rollbackFor = CustomException.class)
public void saveUser(User user) {
    // ...
}

在这个例子中,只有当 saveUser 方法中抛出了 CustomException 或其子类异常时,事务才会被回滚。

注意事项
@Transactional 注解只能用于公共方法上。如果尝试在非公共方法上使用它,则不会生效。

@Transactional 注解的事务管理是通过代理实现的,因此自调用(即一个类中的方法调用该类中的另一个方法)时不会触发事务管理。

默认情况下,Spring 使用 JDBC 或 JPA 的事务管理功能来支持 @Transactional 注解。确保你的项目中包含了相应的事务管理器依赖。

在使用 @Transactional 时,要注意异常的处理,因为异常的类型和处理方式会影响事务的提交或回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个双鱼座的测开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值