-
介绍
- AspectJ是一个基于Java语言的AOP框架
- Spring2.0以后新增了对AspectJ切点表达支持
- @AspectJ是AspectJ1.5新增功能,通过JDK5注解技术,允许Bean类中定义切面,新版本Spring框架,建议使用AspectJ方式来开发AOP
- 主要用途:自定义开发
-
切入点表达式
-
execution() 用于描述方法
<!--创建目标类--> <bean id="userService" class="com.adolph.AOP.jdk.UserServiceImpl"></bean><!--创建切面类--> <bean id="myAspect" class="com.adolph.AOP.jdk.MyAspect"></bean><!--aop编程使用<aop:config>进行配置proxy-target-class="true":使用cglib代理<aop:pointcut>切入点,从目标对象获得具体方法<aop:advisor> 特殊的切面,只有一个通知和一个切入点advice-ref:通知引用pointcut-ref:切入点引用切入点表达式:execution(* com.adolph.AOP.jdk.*.*(..))选择方法 返回值任意 包 类名任意 方法名任意 参数任意 --> <aop:config proxy-target-class="true"><aop:pointcut id="myPointCut" expression="execution(* com.adolph.AOP.jdk.*.*(..))"/><aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/> </aop:config> 复制代码
-
语法:execution(修饰符 返回值 包.类.方法(参数) throws 异常)
- 修饰符:一般省略
- 返回值:*(任意)
- 包
- 省略
- con.adolph.cn 固定包
- com.adolph. adolph包下面子包任意*
- com.adolph.. adolph包下面的所有子包(含自己)
- 省略
- 类
- 省略
- UserServiceImpl 指定类
- *Impl 以Impl结尾
- User 以User开头*
- *. 任意
- 方法名
- 不能省略
- addUser 固定方法
- add 以add开头*
- *Do 以Do结尾
- *. 任意
- 参数
- () 无参
- (int) 一个整型
- (int,int) 两个
- (..) 参数任意
- throws
- 可省略,一般不写
-
综合
`execution(* com.adolph.AOP.jdk.*.*(..))` 复制代码
-
-
-
AspectJ通知类型
- aop联盟定义通知类型,具有特性接口,必须实现,从而确定方法名称
- aspectj 通知类型,只定义类型名称。以及方法格式
- 个数:6种,知道5种,掌握一种
- before:前置通知
- afterReturning:后置通知(应用:常规数据处理)
- around:环绕通知(应用:十分强大,可以做任何事情)
- 方法执行前后分别执行、可以阻止方法的执行
- 必须手动执行目标方法
- afterThrowing:抛出异常通知(应用:包装异常信息)
- after:最终通知(应用:清理现场)
-
基于XML
-
目标类:接口+实现
-
切面类:编写多个通知,采用aspectJ通知名称任意(方法名任意)
-
aop编程:将通知应用到目标类
-
测试
-
目标类
public class UserServiceImpl {public void addUser() {System.out.println("addUser");}public void updateUser() {System.out.println("updateUser");}public void deleteUser() {System.out.println("deleteUser");} } 复制代码
-
切面类
/*** 切面类,含有多个通知*/ public class MyAspect {public void myBefore(JoinPoint joinPoint) {System.out.println("前置通知" + joinPoint.getSignature().getName()); //获得目标方法名}public void myAfterReturning(JoinPoint joinPoint, Object ret) {System.out.println("后置通知" + joinPoint.getSignature().getName() + "____" + ret); //获得目标方法名}public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("前");//手动执行目标方法Object proceed = joinPoint.proceed();System.out.println("后");return proceed;}public void MyAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("抛出异常通知:");}public void after(JoinPoint joinPoint){System.out.println("最终");} } 复制代码
-
xml
<!--创建目标类--> <bean id="userService" class="com.adolph.AOP.jdk.UserServiceImpl"></bean><!--创建切面类--> <bean id="myAspect" class="com.adolph.AOP.jdk.MyAspect"></bean> <!--aop编程 --> <aop:config><!--将切面类 声明成切面,从而获得通知(方法),ref:切面类引用--><aop:aspect ref="myAspect"><!--声明一个切入点,所有的通知都可以使用expression:切入点表达式id:名称用于其他通知引用--><aop:pointcut id="myPointcut" expression="execution(* com.adolph.AOP.jdk.UserServiceImpl.*(..))"></aop:pointcut><!--前置通知method:通知,及方法名pointcut:切入点表达式,此表达式只能当前通知使用pointcut-ref:切入点引用,可以与其他通知点共享切入点通知方法格式:public void myBefore(JoinPoint joinPoint)参数JoinPoint 用于描述连接点(目标方法),获得目标方法名称等--><aop:before method="myBefore" pointcut-ref="myPointcut"></aop:before><!--后置通知,目标方法执行,获得返回值public void myAfterReturning(JoinPoint joinPoint,Object ret)参数1:连接点描述参数2:类型Object,参数名returning配置的--><aop:after-returning method="myAfterReturning" pointcut-ref="myPointcut" returning="ret"></aop:after-returning><!--环绕通知public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable返回值:Object方法名:任意参数:Proceeding JoinPoint抛出异常--><aop:around method="myAround" pointcut-ref="myPointcut"></aop:around><!--异常通知throwing:通知方法的第二个参数名称--><aop:after-throwing method="MyAfterThrowing" pointcut-ref="myPointcut" throwing="e"></aop:after-throwing><!--最终通知--><aop:after method="after" pointcut-ref="myPointcut"></aop:after></aop:aspect> </aop:config> 复制代码
-
-
基于注解
-
替换bean
<!--扫描--> <context:component-scan base-package="com.adolph.AOP"></context:component-scan> 复制代码
@Component public class MyAspect 复制代码
-
必须进行aspectj自动代理
<!--确定aop注解生效--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 复制代码
-
声明切面
@Component @Aspect public class MyAspect 复制代码
-
设置前置通知
@Before("execution(* com.adolph.AOP.jdk.UserServiceImpl.*(..))")public void myBefore(JoinPoint joinPoint) {System.out.println("前置通知" + joinPoint.getSignature().getName()); //获得目标方法名} 复制代码
-
替换公共切入点
@Pointcut("execution(* com.adolph.AOP.jdk.UserServiceImpl.*(..))") private void myPointCut(){} 复制代码
-
设置后置通知
@AfterReturning(value = "myPointCut()",returning = "ret") public void myAfterReturning(JoinPoint joinPoint, Object ret) {System.out.println("后置通知" + joinPoint.getSignature().getName() + "____" + ret); //获得目标方法名 } 复制代码
-
设置环绕通知
@Around(value = "myPointCut()") public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{System.out.println("前");//手动执行目标方法Object proceed = joinPoint.proceed();System.out.println("后");return proceed; } 复制代码
-
设置抛出异常
@AfterThrowing(value = "myPointCut()",throwing = "e") public void MyAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("抛出异常通知:"); } 复制代码
-
最终通知
@AfterThrowing(value = "myPointCut()",throwing = "e") public void MyAfterThrowing(JoinPoint joinPoint,Throwable e){System.out.println("抛出异常通知:"); } 复制代码
-
转载于:https://juejin.im/post/5ca23972e51d453c0f7d8e93