@AspectJ注解配置
Spring注解开发和xml开发 需要jar包 是相同的
第一步: 导入相同的jar包
第二步: 需要在applicationContext.xml 文件中引入 aop名称空间
开启注解自动代理
<!-- 启动AspectJ 注解配置 自动代理 -->
<aop:aspectj-autoproxy />
第三步: AOP编程
1、 目标对象
public class UserDAOImpl implements UserDAO {
@Override
public int save() {
System.out.println("添加");
return 1;
}
2、 切面类和 advice方法
3、 注解配置
使用注解定义切面类
@Aspect
// 类就是一个切面类
public class MyAspect {
// 前置通知 方法
@Before("execution(* cn.itcast.spring.a_aspectj.UserDAOImpl.*(..))")
// 配置切点
public void before(JoinPoint joinPoint) {
System.out.println("前置通知....");
}
第四步: 在spring配置文件中,配置目标Bean、切面Bean
<!-- xml配置 目标bean 和 切面bean -->
<bean id="userDAO" class="cn.itcast.spring.a_aspectj.UserDAOImpl" />
<bean id="myAspect" class="cn.itcast.spring.a_aspectj.MyAspect" />
后置通知@AfterReturning
@AfterReturning(value = "execution(* cn.itcast.spring.a_aspectj.UserDAOImpl.*(..))", returning = "returnVal")
public void afterReturning(JoinPoint joinPoint, Object returnVal) {
System.out.println("后置通知.... 目标方法返回值:" + returnVal);
}
环绕通知@Around
// 性能监控
// @Around("execution(* cn.itcast.spring.a_aspectj.UserDAOImpl.*(..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long begin = System.currentTimeMillis(); // 开始时间
Object result = proceedingJoinPoint.proceed();
long end = System.currentTimeMillis(); // 结束时间
System.out.println(proceedingJoinPoint.toLongString() + "方法执行了" + (end - begin));
return result;
}
应用场景: 性能监控、权限控制 、缓存实现
异常通知@AfterThrowing
@AfterThrowing(value = "execution(* cn.itcast.spring.a_aspectj.UserDAOImpl.*(..))", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println(joinPoint.toLongString() + "方法发生异常:" + e.getMessage());
}
最终通知@After
@After("mypointcut()||mypointcut2()")
// 使用 mypointcut名称切点
public void after(JoinPoint joinPoint) {
System.out.println("最终通知... 释放资源...");
}
小结:
前置通知(权限控制)、 后置通知 —- 不怎么用
环绕通知(权限控制、 性能监控、 缓存技术 )
异常通知 (发生异常后, 记录错误日志 )
最终通知 (释放资源 )
使用注解的好处:不必在xml文件中配置切面
使用@Pointcut注解定义切点
在配置文件 定义
在代码中, 使用 private void 无参数方法 定义 (方法名称 就是切点的名称 )
// 使用@Pointcut 对私有、无返回值、无参数方法 定义切点
@Pointcut("execution(* cn.itcast.spring.a_aspectj.UserDAOImpl.*(..))")
private void mypointcut() {
}
在Advice方法上,就像调用切点方法一样,引用切点
@After("mypointcut()||mypointcut2()")
// 使用 mypointcut名称切点
public void after(JoinPoint joinPoint) {
System.out.println("最终通知... 释放资源...");
}
通过&& 实现两个切点表达式都满足,才拦截
通过|| 实现只要满足一个切点表达式,就可以拦截