AOP的核心概念
AOP(Aspect-Oriented Programming)面向切面编程可以实现横切点与他们所影响的对象之间的解耦。如将公共的日志、权限、事务等业务隔离出来,但不影响原来程序的逻辑性,提高了程序的可重用性,提高了开发效率等。
Aop常用术语:
-
通知:切面的工作
- 前置通知(Before):在目标方法前执行自定义行为。
- 后置通知(After):在目标方法后执行自定义行为。
- 返回通知(After-returning):在目标方法执行后执行自定义行为。
- 异常通知(After-throwing):在目标方法抛出异常后执行自定义行为。
- 环绕通知(Around): 在目标方法调用前和调用后都执行自定义行为。
- 连接点:所有使用通知的应用。
- 切点:所有使用通知的方法。
- 切面:通知和切点的结合。
- 引入:向现有的类添加新方法或属性。
-
织入:把切面应用到目标对象并创建新的代理对象的过程。织入点可分为:
- 编译期:在编译时织入,需要特殊的编译器。
- 类加载期:在目标类加载到JVM时织入,需要特殊的类加载器。
- 运行期:应用运行时织入,AOP容器为目标对象动态创建一个代理对象。SpringAOP以这种方式工作。
AOP注解
- @Aspcet:定义一个切面
- @PointCut:定义一个切点
- @DeclareParents:以透明的方式为被通知的对象引入额外的接口
- @Before:定义一个前置通知
- @After:定义一个后置通知
- @Araound:定义一个环绕通知
- @AfterReturning:定义一个返回通知
- @AfterThrowing:定义一个异常通知
- @EnableAspectJAutoProxy:启动AspectJ自动代理
栗子:
@Aspect
public class AspectDemo{
@PointCut("execution(* 方法名(..))")
public void test(){}
@Before("test()")
public void before() {
}
@After("test()")
public void after() {
}
}
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class AspectConfig {
@Bean
public AspectDemo() {
return new AspectDemo();
}
}
AOP的XML命名空间
- aop:advisor:定义一个通知器
- aop:after:定义一个后置通知
- aop:after-returning:定义一个返回通知
- aop:after-throwing:定义一个异常通知
- aop:around:定义一个环绕通知
- aop:aspect:定义一个切面
- aop:aspectj-autoproxy:启用@AspectJ注解驱动的切面
- aop:before:定义一个前置通知
- aop:config:顶层aop配置元素,其他元素包含在这个元素中。
- aop:declare-parents:以透明的方式为被通知的对象引入额外的接口
- aop-poitcut:定义一个切点
栗子:
<aop-config>
<aop-aspect ref="bean的id">
<aop:before pointcut="execution(* 切点方法名(..))" method="前置通知方法名">
</aop:before>
<aop:after pointcut="execution(* 切点方法名(..))" method="后置通知方法名">
</aop:after>
</aop-aspect>
</aop-config>
Aspect指示器
在SpringAOP中使用Aspect的切点表达式语言来定义切点。
- arg():限制连接点匹配参数为指定类型的执行方法
- @arg():限制连接点匹配参数为指定注解标注的执行方法
- execution():用于匹配连接点的执行方法
- this():限制连接点匹配AOP代理的bean引用为指定类型的方法
- target():限制连接点匹配目标对象为指定类型的方法
- @target():同上用注解标注
- within():限制连接点匹配指定类型
- @within():同上用注解标注
- @annoation():限制匹配带有指定注解的连接点
- bean():匹配限定的bean的ID或者名称的连接点
execution(其他指示器都相同):
- execution()方法可以使用正则表达式定义需要拦截的方法
- 第一参数*表示返回任意类型
- 第二个参数表示拦截的方法
- 第三个参数(..)表示使用任意的参数
栗子:
@Before("execution(* 方法名(..))")
public void before(JoinPoint JoinPoint) {
}
@After("@annotation(自定义接口名字)")
public void after(JoinPoint JoinPoint) {
}
@Around"@annotation(自定义接口名字)")
public void after(ProceedingJoinPoint proceedingJoinPoint) {
}