1、理解必要的专业术语
先看看上面图,这是我的个人理解。(画的丑,主打真实)
1)Advice,通知/增强:类方法中提出来的共性功能(大白话就是提出来的重复代码)
2)Pointcut,切入点/切点:通知返回的方法
3)连接点:方法
4)织入:运行时通知插入到方法的过程
5)aspect,切面:通知功能在什么时候插入到切入点(通知和切入点的结合)
6)目标对象:被增强的对象
7)代理:应用切面的过程(AOP框架使用代理模式创建对象,实现在连接处插入增强)
2、代码练习理解
1)创建两个类
package com.gc;
public class sy {
public void a1(){
// System.out.println("Ac is running ... "); //共性功能
System.out.println("a1 is running...");
}
public void a2(){
// System.out.println("Ac is running ... ");
System.out.println("a2 is running ...");
}
}
package com.gc;
public class AAdvice {
public void Ac(){
System.out.println("Ac is running ... ");
}
}
2)applicationContext.xml配置
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="sy" class="com.gc.sy"/>
<bean id="aopAdvice" class="com.gc.AAdvice"/>
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pt" expression="execution(* *..*.*(..))"/>
<!--配置切面-->
<aop:aspect ref="aopAdvice">
<aop:before method="Ac" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
</beans>
切点表达式:
execution(返回类型 包名.方法名(参数类型)),*:就是所有
*..*,比如包名叫com.gc.hh,正常逻辑写是*.*.*,简写就是*..*
3)测试
package com.bdqn.test;
import com.bdqn.sy;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AAtest {
@Test
public void test(){
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
sy sy=(com.bdqn.sy) cxt.getBean("sy");
sy.a1();
}
}
可以看到增强方法成功插入到切入点了。
这时候肯定有同学问,为什么是插入到前面?注意看applicationContext.xml配置中的aop:before,这是前置增强。
3、Aop五种增强处理
1)前置增强(aop:before):上面代码已经试过了,就是目标方法前织入增强处理
2)最终增强(aop:after):无论目标是否抛出异常,方法最后都会织入增强处理
3)后置增强(aop:after-returning):目标方法正常运行后织入增强处理
4)异常增强(aop:after-throwing):目标方法抛出异常后织入增强处理
5)环绕增强(aop:around):目标方法前后都可以织入增强处理
这里演示一下环绕增强,解决一下疑惑。其他增强处理自己动手试一试。
在上面的代码基础上修改applicationContext.xml:
<!--配置切面-->
<aop:aspect ref="aopAdvice">
<aop:around method="Ac" pointcut-ref="pt"/>
</aop:aspect>
运行测试类:
显示出来增强方法的内容,那切入点方法的内容去哪了? 加入一行代码
package com.bdqn;
import org.aspectj.lang.ProceedingJoinPoint;
public class AAdvice {
public void Ac(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("around_before");
//调用原始方法
joinPoint.proceed();
System.out.println("Ac is running ... ");
}
}
可以看到,在调用原始方法前的内容会插入到切入点方法内容的前面,反之。