原文: https://howtodoinjava.com/spring-aop/aspectj-around-annotation-example/
在此 Spring 操作示例中,我们将学习使用 Aspectj @Around
注解。 @Around
带注解的方法在与切入点表达式匹配的所有方法之前和之后运行。
在此示例中,我们将创建一个简单的 spring 应用程序,添加记录切面周围的内容,然后基于@Around
注解中传递的切入点信息调用切面方法。
1. AspectJ @Around
注解用法
@Around
建议包围了连接点,例如方法调用。 这是最有力的建议。 围绕建议可以在方法调用之前和之后执行自定义行为。 它还负责选择是返回连接点还是通过返回其自身的返回值或引发异常来捷径建议的方法执行。
@Aspect
public class LoggingAspect {
@Around("execution(* com.howtodoinjava.app.service.impl.EmployeeManagerImpl.*(..))")
public void logAroundAllMethods(ProceedingJoinPoint joinPoint) { ... }
@Around("execution(* com.howtodoinjava.app.service.impl.EmployeeManagerImpl.getEmployeeById(..))")
public void logAroundGetEmployee(ProceedingJoinPoint joinPoint) { ... }
}
不要忘记使用ProceedingJoinPoint
作为参数。 您必须调用ProceedingJoinPoint.proceed()
方法,否则将执行原始方法。
2. 项目结构
Spring AOP 项目结构
3. Spring AOP AspectJ maven 依赖项
我添加了 spring 核心,spring aop 和 Aspectj 依赖项。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd;
<modelVersion>4.0.0</modelVersion>
<groupId>com.howtodoinjava</groupId>
<artifactId>SpringAOPExamples</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Spring AOP Examples</name>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
</project>
4. 启用 Spring AOP AspectJ 支持
在 XML 配置文件中,您可以添加aop:aspectj-autoproxy
元素以启用@AspectJ
注解支持。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<!-- Enable @AspectJ annotation support -->
<aop:aspectj-autoproxy />
<!-- Employee manager -->
<bean id="employeeManager" class="com.howtodoinjava.app.service.impl.EmployeeManagerImpl" />
<!-- Logging Aspect -->
<bean id="loggingAspect" class="com.howtodoinjava.app.aspect.LoggingAspect" />
</beans>
5. 需要执行@Around
切面的方法
EmployeeManager.java
和EmployeeManagerImpl.java
public interface EmployeeManager
{
public EmployeeDTO getEmployeeById(Integer employeeId);
public List<EmployeeDTO> getAllEmployee();
public void createEmployee(EmployeeDTO employee);
public void deleteEmployee(Integer employeeId);
public void updateEmployee(EmployeeDTO employee);
}
public class EmployeeManagerImpl implements EmployeeManager
{
public EmployeeDTO getEmployeeById(Integer employeeId)
{
System.out.println("Method getEmployeeById() called");
return new EmployeeDTO();
}
public List<EmployeeDTO> getAllEmployee()
{
System.out.println("Method getAllEmployee() called");
return new ArrayList<EmployeeDTO>();
}
public void createEmployee(EmployeeDTO employee)
{
System.out.println("Method createEmployee() called");
}
public void deleteEmployee(Integer employeeId)
{
System.out.println("Method deleteEmployee() called");
}
public void updateEmployee(EmployeeDTO employee)
{
System.out.println("Method updateEmployee() called");
}
}
6. 编写 AspectJ 注解的类和方法
用切入点信息编写 aspectj 注解的类和方法。
@Aspect
public class LoggingAspect {
@Around("execution(* com.howtodoinjava.app.service.impl.EmployeeManagerImpl.*(..))")
public void logAroundAllMethods(ProceedingJoinPoint joinPoint) throws Throwable
{
System.out.println("****LoggingAspect.logAroundAllMethods() : " + joinPoint.getSignature().getName() + ": Before Method Execution");
try {
joinPoint.proceed();
} finally {
//Do Something useful, If you have
}
System.out.println("****LoggingAspect.logAroundAllMethods() : " + joinPoint.getSignature().getName() + ": After Method Execution");
}
@Around("execution(* com.howtodoinjava.app.service.impl.EmployeeManagerImpl.getEmployeeById(..))")
public void logAroundGetEmployee(ProceedingJoinPoint joinPoint) throws Throwable
{
System.out.println("****LoggingAspect.logAroundGetEmployee() : " + joinPoint.getSignature().getName() + ": Before Method Execution");
try {
joinPoint.proceed();
} finally {
//Do Something useful, If you have
}
System.out.println("****LoggingAspect.logAroundGetEmployee() : " + joinPoint.getSignature().getName() + ": After Method Execution");
}
@Around("execution(* com.howtodoinjava.app.service.impl.EmployeeManagerImpl.createEmployee(..))")
public void logAroundCreateEmployee(ProceedingJoinPoint joinPoint) throws Throwable
{
System.out.println("****LoggingAspect.logAroundCreateEmployee() : " + joinPoint.getSignature().getName() + ": Before Method Execution");
try {
joinPoint.proceed();
} finally {
//Do Something useful, If you have
}
System.out.println("****LoggingAspect.logAroundCreateEmployee() : " + joinPoint.getSignature().getName() + ": After Method Execution");
}
}
7. Spring AspectJ @Around
示例
现在,我们来测试以上配置的切面是否在给定的切入点信息上执行。
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.howtodoinjava.app.model.EmployeeDTO;
import com.howtodoinjava.app.service.EmployeeManager;
public class TestMain
{
@SuppressWarnings("resource")
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeManager manager = (EmployeeManager) context.getBean("employeeManager");
manager.getEmployeeById(1);
manager.createEmployee(new EmployeeDTO());
}
}
****LoggingAspect.logAroundAllMethods() : getEmployeeById: Before Method Execution
****LoggingAspect.logAroundGetEmployee() : getEmployeeById: Before Method Execution
Method getEmployeeById() called
****LoggingAspect.logAroundGetEmployee() : getEmployeeById: After Method Execution
****LoggingAspect.logAroundAllMethods() : getEmployeeById: After Method Execution
****LoggingAspect.logAroundAllMethods() : createEmployee: Before Method Execution
****LoggingAspect.logAroundCreateEmployee() : createEmployee: Before Method Execution
Method createEmployee() called
****LoggingAspect.logAroundCreateEmployee() : createEmployee: After Method Execution
****LoggingAspect.logAroundAllMethods() : createEmployee: After Method Execution
显然,在相关连接点周围执行切面建议。
学习愉快!
参考文献: