AOP
1.什么是AOP
- AOP是一种编程范式,不是编程语言,解决特定的问题。(解决代码重复问题 、关注点分离)
- 面向切面编程(AOP是Aspect Oriented Program的首字母缩写)将应用程序切分成一个个关注点,让每一个关注点成为
独立的,也只做一件事情,尽量不让关注点之间产生耦合。
AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上来说,AOP基本上是通过代理机制实现的。
这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。 - AOP技术它利用一种称为”横切”
的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为”Aspect”,即切面。所谓”切面”
,简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。使用”
横切”
技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
2.基本概念
- 切面(Aspect):对横切性关注点的模块化,其实就是共有功能的实现。如日志切面、权限切面等。
- 连接点(JoinPoint):就是程序在运行过程中能够插入切面的地点。例如,方法调用、异常抛出或字段修改等,但Spring只支持方法级的连接点。
- 通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型。
- 切入点(Pointcut):用于定义通知(Advice)应该切入到哪些连接点(JoinPoint)上。不同的通知通常需要切入到不同的连接点上,这种精准的匹配是由切入点的正则表达式来定义的。
- 目标对象(Target):就是那些即将切入切面的对象,也就是那些被通知的对象。
- 代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象
- 织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。
spring AOP的使用
xml配置
<bean id="advice" class="test.Advice" />
<aop:config>
<aop:aspect id="aspect" ref="advice">
<aop:pointcut id="service" expression="execution(* com.demo.aop.*.find*(..))"/>
<aop:before method="doBefore" pointcut-ref="service"/>
<aop:after method="doAfter" pointcut-ref="service"/>
<aop:around method="doAround" pointcut-ref="service"/>
<aop:after-returning method="doReturn" pointcut-ref="service"/>
<aop:after-throwing method="doThrowing" throwing="ex" pointcut-ref="service"/>
</aop:aspect>
</aop:config>
package test;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class Advice {
private void doBefore(JoinPoint joinPoint) {
}
private Object doAround(ProceedingJoinPoint pjp) throws Throwable {
Object retVal = pjp.proceed();
return retVal;
}
private void doAfter(JoinPoint joinPoint) {
}
private void doReturn(JoinPoint joinPoint) {
}
private void doThrowing(JoinPoint joinPoint,Throwable ex) {
}
}
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.*.*.service.*.*(..))" />
</aop:config>
注解配置
<aop:aspectj-autoproxy/>
@Aspect
@Component
public class MyAspect{
@Pointcut("execution(* com.*.*.service.*.*(..))")
private void piont(){ }
@Before("piont()")
public void beforeTest(){
System.out.println("beforeTest.................");
}
}
execution:用于匹配方法执行的连接点;
within:用于匹配指定类型内的方法执行;
this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
@within:用于匹配所以持有指定注解类型内的方法;
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
@args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
@annotation:用于匹配当前执行方法持有指定注解的方法;
bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;
reference pointcut:表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持。