zl程序教程

您现在的位置是:首页 >  其他

当前栏目

【项目实战】SpringAOP入门介绍,原理与使用

项目入门原理 介绍 实战 使用
2023-09-14 09:04:55 时间

一、SpringAOP入门介绍

1.1 切面

切面是一个横跨多个类和对象的关注点的模块化。
切面可以用于实现日志记录、事务管理、性能测量、安全性等方面的功能,而无需修改这些类的源代码。

在Spring中,我们可以使用AOP(面向切面编程)来实现切面。

1.1 面向切面编程(AOP)

AOP是一种编程范式,旨在通过允许将横切关注点与应用程序的主要业务逻辑分离来增加模块化。
AOP是一种编程范式,它允许我们将横切关注点与对象模型分离,并将其应用于多个类和对象。

1.2 Spring AOP是什么?

Spring AOP是AOP的一种实现,是一种实现面向切面编程(AOP)的框架
Spring AOP允许将横切关注点与应用程序的主要业务逻辑分离,从而增加模块化。
Spring AOP提供了一种在不修改原始方法的源代码的情况下添加方法调用行为的方法。
这些行为包括日志记录、事务管理和安全性
在这里插入图片描述

二、SpringAOP的原理

Spring AOP通过创建拦截目标对象的方法调用的代理对象来工作。
代理对象然后将方法调用委托给目标对象,同时执行在切面中定义的任何其他行为。

在Spring AOP中,动态代理是通过JDK动态代理或CGLIB动态代理实现的。
JDK动态代理是基于接口的代理,它只能代理实现了接口的类。
而CGLIB动态代理是基于类的代理,它可以代理没有实现接口的类。

三、在Spring中使用AOP

要在Spring中使用AOP,可以使用@Aspect注释来定义切面。
例如,如果想要记录每个方法的执行时间,可以定义一个切面如下:

3.1 定义一个切面类

@Aspect
public class TimingAspect {
    @Around("execution(* com.example.myapp.service.*.*(..))")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        System.out.println(joinPoint.getSignature() + " executed in " + (endTime - startTime) + "ms");
        return proceed;
    }
}

在这个例子中,定义了一个名为TimingAspect的切面,并使用@Around注释来定义一个环绕通知。这个通知记录了方法的执行时间,并在控制台上打印出来。

3.2 启用自动代理

要将切面应用于我们的应用程序,需要使用**@EnableAspectJAutoProxy**注释来启用自动代理。例如:

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
    // bean definitions here
}

这将启用自动代理,并将我们的切面应用于我们的应用程序。

四、SpringAOP在SpringBoot中的使用

4.1 添加Spring AOP依赖项到项目

通过将以下内容添加到pom.xml文件中来执行此操作:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${spring.version}</version>
</dependency>

4.2 在Spring配置文件中启用AOP

通过将以下内容添加到配置文件中来执行此操作:

<aop:aspectj-autoproxy />

4.3 创建一个aspect (切面类)

aspect是一个包含advice的类,当到达join point时执行该代码。
您可以通过使用@Aspect注释注释一个类并定义一个或多个切入点和advice方法来创建aspect。
以下是一个例子:

@Aspect
public class LoggingAspect {
    
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before " + joinPoint.getSignature().getName());
    }
    
    @After("execution(* com.example.service.*.*(..))")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("After " + joinPoint.getSignature().getName());
    }
    
}

在这个例子中,

  • @Before advice方法在调用com.example.service包中的任何方法之前执行,
  • @After advice方法在调用com.example.service包中的任何方法之后执行。

4.4 在Spring配置文件中配置aspect

通过将以下内容添加到配置文件中来执行此操作:

<bean id="loggingAspect" class="com.example.aspect.LoggingAspect" />

4.5 在代码中使用aspect

通过使用与您想要执行的advice相对应的切入点表达式注释一个方法来执行此操作。
以下是一个例子:

@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    
    @Transactional
    @Loggable
    public void saveUser(User user) {
        userDao.save(user);
    }
}

在这个例子中,
@Transactional注释告诉Spring管理saveUser方法的事务
@Loggable注释告诉Spring在调用saveUser方法之前和之后执行LoggingAspect类中定义的advice。