<!-- 面向切面(AOP) -->
AOP:所谓面向切面编程,是一种通过预编译和运行期动态代理的方式实现在不修改源代码的情况下给程序动态添加功能的技术.
AOP专业术语:
1.增强处理(Advice)通常所说的重复的代码,提出来的公共代码
2.连接点(JoinPoint)基本所有方法都是连接点,就是你可以通知advice增强的方法
3.切入点(Pointcut)从连接点中筛选出来的你想增强的方法,也就是被织入的方法
4.切面(Aspect)通过@Before,@After,@Around,@AfterReturning等
5.引入(introduction)
6.目标(target)被通知的类,在XML中指定的类
7.代理(proxy)
8.织入(weaving)把切面的advice和切入点绑定的过程
<!-- 通过XML实现AOP -->
<bean id="serviceAspect" class="aop.MyAspect"></bean>
<!-- 用XML方式实现AOP -->
<aop:config >
<aop:pointcut expression="execution(public * *(..))" id="pointcut"/>
<aop:aspect ref="serviceAspect">
<aop:before method="beforeAdvice" pointcut-ref="pointcut"/>
<aop:after-returning method="afterAdvice" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
<!-- 注解方式实现AOP-->
XML的配置:
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 记得开启spring的注解扫描 -->
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="*"></context:component-scan>
一个切面类:
package aop;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
/*
* 重复的日志记录
* 切面
*/
//我是切面(重复代码+切入点)
@Component
@Aspect
public class MyAspect {
private Logger logger=Logger.getLogger(MyAspect.class);
/**
* 增强手段有哪些:前置@Before,后置@AfterReturning,最终@After,异常@AfterThrowing,环绕@Around
* 所有增强方法都可以有一个参数叫做joinPoint,描述了当前方法的信息
*/
@Before("execution(public * *(..))")
public void beforeAdvice(JoinPoint joinPoint) {
logger.info("before:记录一堆日志信息"+joinPoint.getSignature().getName());//获得调用的方法名
}
//后置增强,发生异常不执行
@AfterReturning("execution(public * *(..))")
public void afterReturningAdvice(JoinPoint joinPoint) {
logger.info("afterReturning:记录一堆日志信息");
}
//相当于finally
//excution(访问权限修饰符? 返回类型 (包名类名?) 方法匹配(参数匹配) )
@After("execution(public * *(..))")
public void afterAdvice(JoinPoint joinPoint) {
logger.info("after:记录一堆日志信息");
}
//方法多个参数,必须要给切入点表达式,配置个throwing="e"
@AfterThrowing(value="execution(public * *(..))",throwing="e")
public void throwAdvice(JoinPoint joinPoint,Throwable e) {
logger.info("发生异常"+e.getMessage());
}
}
切入点表达式
excution(访问权限修饰符? 返回类型 (包名类名?) 方法匹配(参数匹配) )
?问号可选,其余必写
<!-- 【拦截所有public方法】 -->
<!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->
<!-- 【拦截所有save开头的方法 】 -->
<!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->
<!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
<!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>-->
<!-- 【拦截指定类的所有方法】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>-->
<!-- 【拦截指定包,以及其自包下所有类的所有方法】 ..两个点代表及其子包,自后一个星代表方法 -->
<!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->
<!-- 【多个表达式】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!-- 下面2个且关系的,没有意义 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) && execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!-- 【取非值】 -->
<!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>