AOP(Aspect Oriented Programming)向切面编程,是Spring技术体系中的两大核心思想之一,它解决了垂直方向面向对象思想想要完成例如日志、性能检测等系统代码太过冗余不易维护的问题,底层使用了动态代理和反射的机制。
Aop三种实现方式:
-
使用spring自己的aop
①定义通知类,实现“通知”接口,例如MethodBeforeAdvice(前置通知)、AfterReturningAdvice(后置通知)、MethodInterceptor(环绕通知、拦截器),重写对应的通知方法。
public class LogAdvice implements MethodBeforeAdvice, AfterReturningAdvice { @Override public void before(Method method, Object[] objects, Object target) throws Throwable { } @Override public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable { } }
②配置xml:
核心:BeanNameAutoProxyCreator(根据名称自动代理创建),注入名称规则和通知列表
通知列表可以注入Advisor(Advice通知 + Pointcut切入点),将切入规则具体到通过正则表达式匹配到的方法。<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <!--Bean名称规则(数组):指定哪些bean创建自动代理--> <property name="beanNames"> <list> <value>*ServiceBean</value> </list> </property> <!--通知列表--> <property name="interceptorNames"> <list> <value>logAdviceBean</value> <value>performanceAdvisorBean</value> </list> </property> </bean>
-
使用AspectJ框架 ( xml为主形式 )
①定义切面类,自定义通知方法。
public class LogAspect { // 前置通知 public void doBefore(JoinPoint joinPoint) { } // 后置通知:方法正常执行后,有返回值,执行该后置通知;如果该方法执行出现异常,则不执行该后置通知 public void afterReturningAdvice(JoinPoint joinpoint, Object returnVal) { } // 后置通知 public void afterAdvice(JoinPoint joinpoint) { } // 异常通知:方法出现异常时,执行该通知 public void throwingAdvice(JoinPoint joinpoint, Exception ex) { } // 环绕通知 public Object aroundAdvice(ProceedingJoinPoint joinpoint) throws Throwable { return returnVal; } }
②配置xml:
核心:使用spring-aop进行配置,注入切面,在切面内注入切点(关键表达式)并配置通知。<aop:config> <!--注入切面--> <aop:aspect ref="logAspectBean"> <!--注入切点--> <aop:pointcut id="serviceMethodPointcut" expression="execution(* com.apesource.service.impl.*.create*(..))"/> <!--配置“前置通知”--> <!--在pointcut切入点查找到的方法前,执行当前logAspectBean的doBefore--> <aop:before method="doBefore" pointcut-ref="serviceMethodPointcut"/> <!--配置“后置通知”--> <!--returning属性:配置当前方法中用来接收返回值的参数名--> <aop:after-returning returning="returnVal" method="afterReturningAdvice" pointcut-ref="serviceMethodPointcut"/> <aop:after method="afterAdvice" pointcut-ref="serviceMethodPointcut"/> <!--配置“异常通知”--> <!--throwing属性:配置当前方法中用来接收当前异常的参数名--> <aop:after-throwing throwing="ex" method="throwingAdvice" pointcut-ref="serviceMethodPointcut"/> <!--配置环绕通知--> <aop:around method="aroundAdvice" pointcut-ref="serviceMethodPointcut"/> </aop:aspect> </aop:config>
-
使用AspectJ框架 ( 注解 )
①定义切面类,自定义通知方法。以注解方式声明
@Component @Aspect public class LogAspect { private static final String POINTCUT_EXPRESSION = "execution(* com.apesource.service.impl.*.create*(..) )"; /** * 前置通知 */ @Before(POINTCUT_EXPRESSION) public void doBefore(JoinPoint joinPoint) { } /** * 后置通知:方法正常执行后,有返回值,执行该后置通知;如果该方法执行出现异常,则不执行该后置通知 */ @AfterReturning(value = POINTCUT_EXPRESSION, returning = "returnVal") public void afterReturningAdvice(JoinPoint joinpoint, Object returnVal) { } /** * 后置通知 */ @After(POINTCUT_EXPRESSION) public void afterAdvice(JoinPoint joinpoint) { } /** * 异常通知:方法出现异常时,执行该通知 */ @AfterThrowing(value = POINTCUT_EXPRESSION, throwing = "ex") public void throwingAdvice(JoinPoint joinpoint, Exception ex) { } /** * 环绕通知 */ @Around(POINTCUT_EXPRESSION) public Object aroundAdvice(ProceedingJoinPoint joinpoint) throws Throwable { return returnVal; } }
②配置xml:
<!--自动扫描器--> <context:component-scan base-package="com.apesource"/> <!--配置AspectJ的自动代理--> <aop:aspectj-autoproxy/>