(1)AspectJ注解
-
@Aspect 定义一个切面,注解在切面类上
-
@PointCut(“execution( * aspectj.dao . * . * (…) )”),
-
如:
@Pointcut( "execution(* com.ming.anno.aop.Target.*(..))" )
-
execution() 表达式主体
访问权限修饰符可省略
第一个*表示的是返回类型
aspectj.dao:需要匹配的包名
第二个*表示的是类名
第三个*表示的是方法名
(…)表示方法的参数
注意:
- 访问修饰符可以省略
- 返回值类型、包名、类名、方法名可以使用星号*代表任意
- 包名与类名之间一个点. 代表当前包下的类,两个点… 表示当前包及其子包下的类
- 参数列表可以使用两个点… 表示任意个数,任意类型的参数列表
-
-
@Before 前置通知
-
@AfterRunning 后置返回通知,目标方法成功执行后实施增强
-
@After 后置(最终)通知,目标方法执行后实施增强,不论是否发生异常
-
@Around 环绕通知
-
@AfterThrowing 异常通知
-
@EnableAspectJAutoProxy:开启Spring对AspectJ的支持
(2)过程:
1、引入依赖:
<dependency> <!-- spring-context中包含aop --> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.5.RELEASE</version> </dependency> <dependency> <!-- AspectJ织入器 --> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.6</version> </dependency>
2、创建目标接口和目标类
public interface TargetInterface { void sayHello(); void divideByZero(); } public class Target implements TargetInterface { public void sayHello() { System.out.println("Hello!"); } public void divideByZero() { //使用try catch包裹则执行AfterReturning增强 try { System.out.println(10/0); } catch (Exception e) { e.printStackTrace(); } //不使用try catch包括则执行AfterThrowing增强 System.out.println(10/0); } }
3、创建切面类
public class Advice { public void before() { System.out.println("Before:Hello!"); } public void afterRunning() { System.out.println("AfterReturning:Hello!"); } public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("Around1:Hello!"); Object proceed = pjp.proceed(); System.out.println("Around2:Hello!"); return proceed; } public void afterThrowing() { System.out.println("AfterThrowing:Hello!"); } public void after() { System.out.println("After:Hello!"); } }
4、在Spring容器中注册目标类和切面类(IOC)
5、在Spring核心配置文件中配置织入关系(记得导入aop的xsd约束)
- 基于XML形式:
<!--目标对象--> <bean id="target" class="com.ming.aop.Target"/> <!--增强对象:通知方法--> <bean id="advice" class="com.ming.aop.Advice"/> <!--配置织入关系--> <aop:config> <!--配置切面--> <aop:aspect id="myAspect" ref="advice"> <!--定义切面表达式(抽取)--> <aop:pointcut id="myPointcut" expression="execution(* com.ming.aop.Target.*(..))"/> <!--定义前置通知方法--> <aop:before method="before" pointcut-ref="myPointcut"/> <!--定义后置返回通知--> <aop:after-returning method="AfterReturning" pointcut-ref="myPointcut"/> <!--定义异常通知--> <aop:after-throwing method="afterThrowing" pointcut-ref="myPointcut"/> <!--定义后置通知--> <aop:after method="after" pointcut-ref="myPointcut"/> <!--定义环绕通知--> <aop:around method="around" pointcut-ref="myPointcut"/> </aop:aspect> </aop:config>
基于注解形式:
- 为目标类和切面类添加@Component注解,同时修改切面类如下:
package com.ming.anno.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; /** * @author Cao * @date 2021/08/16 */ @Component("adviceAnno") @Aspect public class Advice { @Before("myPointcut()") public void before() { System.out.println("Before:Hello!"); } @AfterReturning("myPointcut()") public void afterRunning() { System.out.println("AfterRunning:Hello!"); } @Around("myPointcut()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("Around1:Hello!"); Object proceed = pjp.proceed(); System.out.println("Around2:Hello!"); return proceed; } @AfterThrowing("myPointcut()") public void afterThrowing() { System.out.println("AfterThrowing:Hello!"); } @After("myPointcut()") public void after() { System.out.println("After:Hello!"); } /** * 抽取切点表达式 */ @Pointcut("execution(* com.ming.anno.aop.Target.*(..))") public void myPointcut() { } }
在Spring核心配置类中开启组件扫描和AspectJ自动代理
<!--测试基于注解开发AspectJ--> <context:component-scan base-package="com.ming.anno.aop"/> <!--开启AspectJ自动代理,不开启无法实现增强--> <aop:aspectj-autoproxy/>