52.介绍AOP有几种实现方式
- Spring 1.2 基于接口的配置:最早的 Spring AOP 是完全基于几个接口的,想看源码的同学可以从这里起步。
- Spring 2.0 schema-based 配置:Spring 2.0 以后使用 XML 的方式来配置,使用 命名空间 <aop ></aop>
- Spring 2.0 @AspectJ 配置:使用注解的方式来配置,这种方式感觉是最方便的,还有,这里虽然叫
做 @AspectJ,但是这个和 AspectJ 其实没啥关系。采用AspectJ 进行动态织入的方式实现AOP,需要用AspectJ 单独编译。
额外扩展(AOP代码实现)
1.基于XML的声明式AspectJ
- 基于XML的声明式AspectJ是指通过XML文件来定义切面、切入点及通知,所有的切面、切入点和通知都必须定义在<aop:config>元素内。
- Spring配置文件中的<beans>元素下可以包含多个<aop:config>元素,一个<aop:config>元素中又可以包含属性和子元素,其子元素包括<aop:pointcut>、<aop:advisor>和<aop:aspect>。
- 在配置时,这3个子元素必须按照此顺序来定义。在<aop:aspect>元素下,同样包含属性和多个子元素,通过使用<aop:aspect>元素及其子元素就可以在XML文件中配置切面、切入点和通知。常用元素的配置代码如下所示。
<!-- 定义切面Bean -->
<bean id="myAspect" class="com.ssm.aspectj.xmL.MyAspect" />
<aop:config>
<!-- 1.配置切面 -->
<aop:aspect id="aspect" ref="myAspect">
<!-- 2.配置切入点 -->
<aop:pointcut id="myPointCut" expression="execution(* com.ssm.aspectj.*.*(..))" />
<!-- 3.配置通知-->
<!-- 前置通知-->
<aop:before method="myBefore" pointcut-ref="myPointCut" />
<!-- 后置通知 -->
<aop:after-returning method="myAfterReturning"
pointcut-ref="myPointCut" returning="returnVal" />
<!-- 环绕通知-->
<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:config>
2.基于注解的声明式AspectJ
- 基于XML的声明式AspectJ实现AOP编程虽然便捷,但是存在一些缺点,那就是要在Spring文件中配置大量的代码信息。为了解决这个问题,AspectJ框架为AOP的实现提供了一套注解,用以取代Spring配置文件中为实现AOP功能所配置的臃肿代码。关于AspectJ注解的介绍如表所示
切面类LogAapectj
package com.powernode.demo04;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect // 标志这个类是一个切面
public class LogAapectj{
@Before("execution(* com.powernode.demo04.userviceImpl.*(..))")
public void before() {
System.out.println("---- 发法执行前-----");
}
@After("execution(* com.powernode.demo04.userviceImpl.*(..))")
public void after() {
System.out.println("---- 发法执行后-----");
}
// 加入环绕增强
@Around("execution(* com.powernode.demo04.userviceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("环绕前");
// 执行发法
Object proceed = jp.proceed();
System.out.println("环绕后");
}
}
<!-- 方式三 使用注解 -->
<bean id="annotation" class="com.powernode.demo04.LogAapectj"/>
<!-- 开启注解 JDK(默认 expose-proxy="false" ) cglib(expose-proxy="true") -->
<aop:aspectj-autoproxy expose-proxy="false"/>