一、概述
在 Spring 中,尽管使用 XML 配置文件可以实现 AOP 开发,但是如果所有的相关配置都集中在配置文件中,势必会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。
为此,AspectJ 框架为 AOP 开发提供了一套注解。AspectJ 允许使用注解定义切面、切入点和增强处理,Spring 框架可以根据这些注解生成 AOP 代理。
名称 | 说明 |
---|---|
@Aspect | 用于定义一个切面。 |
@Pointcut | 用于定义一个切入点。 |
@Before | 用于定义前置通知,相当于 BeforeAdvice。 |
@AfterReturning | 用于定义后置通知,相当于 AfterReturningAdvice。 |
@Around | 用于定义环绕通知,相当于MethodInterceptor。 |
@AfterThrowing | 用于定义抛出通知,相当于ThrowAdvice。 |
@After | 用于定义最终final通知,不管是否异常,该通知都会执行。 |
@DeclareParents | 用于定义引介通知,相当于IntroductionInterceptor(不要求掌握)。 |
启用 @AspectJ 注解有以下两种方法:
1)使用@Configuration和@EnableAspectJAutoProxy注解
@Configuration @EnableAspectJAutoProxy public class Appconfig { }
2)基于XML配置
<aop:aspectj-autoproxy>
3)相关类库的引用,参考上一篇文章Spring深入浅出(十二),AOP,基于XML开发
二、基于 AOP 的 @AspectJ 示例
1. 创建aspect 模块
package com.clzhang.spring.demo; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.AfterReturning; @Aspect public class Logging { /** * Following is the definition for a pointcut to select all the methods * available. So advice will be called for all the methods. */ @Pointcut("execution(* com.clzhang.spring.demo.*.*(..))") private void selectAll() { } /** * This is the method which I would like to execute before a selected method * execution. */ @Before("selectAll()") public void beforeAdvice() { System.out.println("Going to setup student profile."); } /** * This is the method which I would like to execute after a selected method * execution. */ @After("selectAll()") public void afterAdvice() { System.out.println("Student profile has been setup."); } /** * This is the method which I would like to execute when any method returns. */ @AfterReturning(pointcut = "selectAll()", returning = "retVal") public void afterReturningAdvice(Object retVal) { System.out.println("Returning:" + retVal.toString()); } /** * This is the method which I would like to execute if there is an exception * raised by any method. */ @AfterThrowing(pointcut = "selectAll()", throwing = "ex") public void AfterThrowingAdvice(IllegalArgumentException ex) { System.out.println("There has been an exception: " + ex.toString()); } }
2. 创建Bean类
package com.clzhang.spring.demo; public class Student { private Integer age; private String name; public void setAge(Integer age) { this.age = age; } public Integer getAge() { System.out.println("Age : " + age); return age; } public void setName(String name) { this.name = name; } public String getName() { System.out.println("Name : " + name); return name; } public void printThrowException() { System.out.println("Exception raised"); throw new IllegalArgumentException(); } }
3. 创建主程序
package com.clzhang.spring.demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); Student student = (Student) context.getBean("student"); System.out.println("-----Invoke getName begin-----"); String myName = student.getName(); System.out.println("-----Invoke getName end. Name is:" + myName + "----"); student.getAge(); student.printThrowException(); } }
4. 创建配置文件
<?xml version="1.0" encoding="UTF-8"?> <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 "> <aop:aspectj-autoproxy/> <!-- Definition for student bean --> <bean id="student" class="com.clzhang.spring.demo.Student"> <property name="name" value="Zara" /> <property name="age" value="11"/> </bean> <!-- Definition for logging aspect --> <bean id="logging" class="com.clzhang.spring.demo.Logging"/> </beans>
5. 运行输出
-----Invoke getName begin----- Going to setup student profile. Name : Zara Student profile has been setup. Returning:Zara -----Invoke getName end. Name is:Zara---- Going to setup student profile. Age : 11 Student profile has been setup. Returning:11 Going to setup student profile. Exception raised Student profile has been setup. There has been an exception: java.lang.IllegalArgumentException
本文参考:
https://www.w3cschool.cn/wkspring/k4q21mm8.html