一、AOP理解
1、AOP
中文名称面向切面编程 ,英文名称:( Aspect Oriented Programming ),正常程序执行流程都是纵向执行流程,而AOP则是在原有纵向执行流程中添加横切面,不需要修改原有程序代码,体现了高扩展性。并且将原有功能相当于释放了部分逻辑,让职责更加明确。综上,在程序原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面过程就叫做面向切面编程。
2、切面常用概念
1】切点(point cut):原有的程序功能。
2】前置通知(before advice):在切点之前执行的功能。
3】后置通知(after advice):在切点之后执行的功能
4】异常通知(throws advice):如果切点执行过程中出现异常,会触发异常通知。
上述所有功能,统称为:切面(Aspect)。
3、织入的概念:
织入(Weaving)就是把切面嵌入到原有功能的过程。
4、spring 提供了 2 种 AOP 实现方式
1】Schema-based
每个通知都需要实现接口或类,配置 spring 配置文件时在<aop:config>配置。
2】AspectJ
每个通知不需要实现接口或类,配置 spring 配置文件是在<aop:config>的子标签<aop:aspect>中配置。
二、AOP代码实例
本实例是使用注解方式实现,使用注解前先看一下常用注解的概念及代表的意义。
1】常用注解概念及意义
@Component:
相当于<bean/>,定义设为切点的类
@Component(“自定义名称”),自定义名称一般取类名即可,代码如下:
@Component("Book")
public class Book {
public void looking() {
System.out.println("====>现在开始看书!!!");
}
}
@Aspect
注明此类为AOP类
@Pointcut
定义切点,在切点方法上,和切点类中的方法一致。
@Before
前置通知
@After
后置通知
@Around
环绕通知,把前置通知和后置通知都写到一个通知中,组成了环绕通知(注意要有ProceedingJoinPoint参数传入)。
@Component("AnnotationTest")
@Aspect
public class AnnotationTest {
// 定义切点
@Pointcut("execution(* *.looking(..))")
public void looking(){}
/**
* 前置通知(注解中的sayings()方法,其实就是上面定义pointcut切点注解所修饰的方法名,那只是个代理对象,不需要写具体方法,
* 相当于xml声明切面的id名,如下,相当于id="embark",用于供其他通知类型引用)
* <aop:config>
<aop:aspect ref="mistrel">
<!-- 定义切点 -->
<aop:pointcut expression="execution(* *.saying(..))" id="embark"/>
<!-- 声明前置通知 (在切点方法被执行前调用) -->
<aop:before method="beforSay" pointcut-ref="embark"/>
<!-- 声明后置通知 (在切点方法被执行后调用) -->
<aop:after method="afterSay" pointcut-ref="embark"/>
</aop:aspect>
</aop:config>
*/
@Before("looking()")
public void sayHello(){
System.out.println("注解类型前置通知");
}
//后置通知
@After("looking()")
public void sayGoodbey(){
System.out.println("注解类型后置通知");
}
// 环绕通知。注意要有ProceedingJoinPoint参数传入。
@Around("looking()")
public void sayAround(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("注解类型环绕通知..环绕前");
pjp.proceed();//执行方法
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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd ">
<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:config.properties" />
<!-- 自动扫描(自动注入),自动扫描service包下的文件,找到注释是以@Service为开头的类名,
自动变成spring上下文文件中,变成一个bean(实体与模型的抽离)
如果选择手动配置,那就是一项一项的配置,相当费时间,而且需要总改此xml文件。
-->
<context:component-scan base-package="bigtec.aop" />
<!-- 开启aop注解方式,此步骤不能少,这样java类中的aop注解才会生效 -->
<aop:aspectj-autoproxy/>
</beans>
测试类如下:
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring-aop.xml");
Book br = (Book) ac.getBean("Book");
br.looking();
System.out.println(ac.toString());
}
}