前言:
AOP并不是Spring框架特有的。Spring只是支持AOP编程 (面向切面编程) 的框架之一。
概念:
1、切面(Aspect)
一系列Advice + Pointcut 的集合。
2、通知(Advice)
通知是切面开启后,切面的方法。
- 前置通知 ( before ):在动态代理反射原有对象方法 或者 执行环绕通知 前 执行的通知功能
- 后置通知(after):在动态代理反射原有对象方法 或者 执行环绕通知 后 执行的通知功能
- 返回通知 (afterReturning):在动态代理反射原有对象方法 或者 执行环绕通知 后 正常返回(无异常)执行的通知功能
- 异常通知(afterTherowing):在动态代理反射原有对象方法 或者 执行环绕通知 产生异常后执行的通知功能
- 环绕通知(around):在动态代理中,它可以取代当前被拦截对象的方法,提供回调原有被拦截对象的方法
3、引入(Introduction)
引入允许我们在现有的类里添加自定义的类和方法
4、切点(Pointcut)
这是一个告诉Spring AOP 在什么时候启动拦截并织入对应的流程,因为并不是所有的开发都是需要启动AOP的,它往往通过正则表达进行限定
5、连接点( join point)
Pointcut 中的某个具体位置。
首先要有 AspectJ 的依赖
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.2</version> </dependency>
现在我们去创建一个Cat 类 (目标类)出来,并使用@Component 注入容器中
import org.springframework.stereotype.Component; //目标类 @Component public class Cat { public void eat(){ System.out.println("小白猫,开始吃鱼了!!!!"); } }
然后再创一个 切面类 出来
@Component @Aspect public class CatAdvice {//切面类 //execution (* *.*(..) ) // 第一个* 代表着 返回类型是任意的 // 第二个* 代表着 类的全限定名 * 代表着所有 // *(..) 代表着 任意方法 任意的参数 // 比如 execution ( void com.oukele.learning.aop2.Cat.eat()) //切点 @Pointcut("execution(* *.*(..))") public void pointcut(){}; @Before("pointcut()") public void clean(){//在猫吃之前执行的方法 ,把鱼清洗一下 (前置通知) System.out.println("现在我们把我这条鱼,清洗一下"); } @After("pointcut()") public void tidy(){//猫吃完鱼后执行的方法,收拾一下剩下的残渣 (后置通知) System.out.println("收拾,小白猫吃剩下来的残渣。!!!"); } }
再创一个配置类
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration//声明当前类是配置类 ( 类似于 xml 文件一样 ) @ComponentScan(basePackages = "com.oukele.learning.aop2")//扫描某个包中的注解 @EnableAspectJAutoProxy//激活 代理功能 public class SpringConfig { }
现在开始测试啦
public class Main { public static void main(String[] args) { //加载配置类 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); //从容器中获取Cat类 Cat cat = context.getBean(Cat.class); cat.eat();//调用Cat类的方法 } }
结果:
1 现在我们把我这条鱼,清洗一下 2 小白猫,开始吃鱼了!!!! 3 收拾,小白猫吃剩下来的残渣。!!!
只要我们把切面类里面的@Componet去掉,就会发现,这只猫,是直接吃鱼的。
这就是面向切面编程。。。。
代码示例下载:https://github.com/nongzihong/Spring-AspectJ-Annotion