1.什么是AspectJ
AspectJ
是一个基于
Java
语言的
AOP
框架。在
Spring 2.0
以后,新增了对
AspectJ
框
架的支持。在
Spring
框架中建议使用
AspectJ
框架开发
AOP
。
2.AspectJ
框架中的通知类型
![](https://i-blog.csdnimg.cn/blog_migrate/4929f8f6e784c3888f16fe4b246e34a5.png)
3.AspectJ 框架配置 AOP 方式
3.1通过 XML
文件配置
AOP
通过
AspectJ
配置方式
通过
Spring
的
Schema_based
方式
3.2 通过注解配置
AOP
4.AspectJ 配置方式
AspectJ
配置方式是指使用
AspectJ
框架的配置方式来配置切面。在使用
AspectJ
配置切
面时,切面不需要实现一些特定的接口。
1.编写切面类
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class MyAspect { /** * 前置通知 * @param joinPoint 对目标对象的封装 */ public void myBefore(JoinPoint joinPoint){ //joinPoint.getTarget(); 获取目标对象 //joinPoint.getSignature().getName(); 获取目标方法名 //joinPoint.getArgs(); 获取目标方法参数列表 //joinPoint.getThis(); 获取代理对象 System.out.println("Before "+joinPoint.getSignature().getName()); } /** * 后置通知 * @param joinPoint */ public void myAfterReturning(JoinPoint joinPoint){ System.out.println("After "+joinPoint.getSignature().getName()); } /** * 环绕通知 * @param proceedingJoinPoint * @return * @throws Throwable */ public Object myAround(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{ System.out.println("Around Before "+proceedingJoinPoint.getSignature().getName()); Object obj = proceedingJoinPoint.proceed(); System.out.println("Around After "+proceedingJoinPoint.getSignature().getName()); return obj; } /** * 异常通知类型 * @param e */ public void myAfterThrowing(Exception e){ System.out.println("Exception "+e); } public void myAfter(){ System.out.println("最终通知"); } } |
2.编写配置文件
<?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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--配置目标对象--> <bean id="usersService" class="com.aspectj.service.impl.UsersServiceImpl"/> <!--配置切面对象--> <bean id="myAspect" class="com.aspectj.aop.MyAspect"/> <!--配置切面对象--> <bean id="myAspect2" class="com.aspectj.aop.MyAspect2"/> <!-- 配置切面--> <aop:config> <aop:aspect id="my1" ref="myAspect" order="1"> <!-- 配置切点--> <aop:pointcut id="myPointcut" expression="execution(* com.aspectj.service.*.*(..))"/> <!--前置通知--> <aop:before method="myBefore" pointcut-ref="myPointcut"/> <!--后置通知--> <aop:after-returning method="myAfterReturning" pointcut-ref="myPointcut"/> <!--环绕通知--> <aop:around method="myAround" pointcut-ref="myPointcut"/> <!--配置异常通知--> <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointcut" throwing="e"/> <!--最终通知--> <aop:after method="myAfter" pointcut-ref="myPointcut"/> </aop:aspect> <!--配置切面--> <aop:aspect id="my2" ref="myAspect2" order="2"> <aop:pointcut id="myPointcut2" expression="execution(* com.aspectj.service.*.*(..))"/> <aop:before method="myAspectBefore" pointcut-ref="myPointcut2"/> </aop:aspect> </aop:config> </beans> |
注意:在 AspectJ 配置方式中,可以添加多个<aop:aspect>标签实现多切面配置。在<aop:aspect> 标签中包含 order 属性用于配置执行切面的执行顺序。
5.Schema_based 配置方式
Schema_based(
基础模式
)
配置方式是指使用
Spring AOP
模块来定义切面并在
AspectJ
框架中对该切面进行配置。要求切面在定义通知类型时,
需要实现特定接。
编写切面类
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.AfterReturningAdvice; import org.springframework.aop.MethodBeforeAdvice; import org.springframework.aop.ThrowsAdvice; import java.lang.reflect.Method; public class BasedMyAspect implements MethodBeforeAdvice, AfterReturningAdvice, MethodInterceptor, ThrowsAdvice { /** * 环绕通知 * @param methodInvocation * @return * @throws Throwable */ @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("Around Before"); Object obj = methodInvocation.proceed(); System.out.println("Around After"); return obj; } /** * 后置通知 * @param o * @param method * @param objects * @param o1 * @throws Throwable */ @Override public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable { System.out.println("After."); } /** * 前置通知 * @param method * @param objects * @param o * @throws Throwable */ @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("Before"); } /** * 异常通知 * @param ex */ public void afterThrowing(Exception ex){ System.out.println("Exception: "+ex); } } |
配置文件
<?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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--配置目标对象--> <bean id="basedUsersService" class="com.schema_based.service.impl.BasedUsersServiceImpl"/> <!--配置切面对象--> <bean id="basedMyAspect" class="com.schema_based.aop.BasedMyAspect"/> <!--配置切面对象--> <bean id="basedMyAspect2" class="com.schema_based.aop.BasedMyAspect2"/> <!--配置切面--> <aop:config> <!-- 配置切点--> <aop:pointcut id="basedMyPointcut" expression="execution(* com.schema_based.service.*.*(..))"/> <!--配置切面--> <aop:advisor id="my1" advice-ref="basedMyAspect" pointcut-ref="basedMyPointcut" order="1"/> <aop:advisor id="my2" advice-ref="basedMyAspect2" pointcut-ref="basedMyPointcut" order="2"/> </aop:config> </beans> |
注意:在 Schema_based 配置方式中,可以添加多个<aop:advisor>标签实现多切面配置。在 <aop:advisor>标签中包含 order 属性用于配置执行切面的执行顺序
6.注解配置方式
AspectJ
框架允许使用注解定义切面、切入点和增强处理,而
Spring
框架则可以识别并 根据这些注解生成 AOP
代理。
常用注解
常用注解 | 注解说明 |
@Before
|
前置通知
|
@AfterReturning
|
后置通知
|
@Around
|
环绕通知
|
@After
|
最终通知
|
@Pointcut
|
配置切点
|
@Aspect
|
指定切面
|
@Order
|
执行顺序
(
此注解由
Spring
提供
)
|
实例:
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.core.annotation.Order; @Aspect //指定当前对象为切面对象 @Order(2) public class MyAspect { /** * 配置切点 */ @Pointcut("execution(* com.bjsxt.service.*.*(..))") public void myPointcut(){ } /** * 前置通知 * @param joinPoint */ //@Before("execution(* com.bjsxt.service.*.*(..))") @Before("myPointcut()") public void myBefore(JoinPoint joinPoint){ System.out.println("Before...."+joinPoint.getSignature().getName()); } /** * 后置通知 * @param joinPoint */ //@AfterReturning("execution(* com.bjsxt.service.*.*(..))") @AfterReturning("myPointcut()") public void myAfterRetuning(JoinPoint joinPoint){ System.out.println("AfterRetuning "+joinPoint.getSignature().getName()); } /** * 环绕通知 * @param proceedingJoinPoint * @return * @throws Throwable */ //@Around("execution(* com.bjsxt.service.*.*(..))") @Around("myPointcut()") public Object myAround(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{ System.out.println("Around Before "); Object proceed = proceedingJoinPoint.proceed(); System.out.println("Around After"); return proceed; } /** * 最终通知 */ // @After("execution(* com.bjsxt.service.*.*(..))") @After("myPointcut()") public void myAfter(){ System.out.println("最终通知"); } /** * 异常通知 * @param e */ //@AfterThrowing(value = "execution(* com.bjsxt.service.*.*(..))",throwing = "e") @AfterThrowing(value = "myPointcut()",throwing = "e") public void myAfterThrowing(Exception e){ System.out.println("Exception: "+e); } } |
相关配置文件
<?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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置目标对象-->
<bean id="usersService" class="com.service.impl.UsersServiceImpl"/>
<!--配置切面对象-->
<bean id="myAspect" class="com.aop.MyAspect"/>
<bean id="myAspect2" class="com.aop.MyAspect2"/>
<!--在AspectJ框架中开启注解处理。声明自动为IOC容器的那些配置了@AspectJ的切面的bean对象创建代理,织入切面。-->
<!--默认为false:false:使用JDK的Proxy对象创建代理对象。true:使用CGLIB创建代理对象。如果目标对象实现了接口会使用Proxy,如果目标
对象没有实现接口则自动使用CGLIB创建代理对象。-->
<aop:aspectj-autoproxy proxy-target-class="false"/>
</beans> |