使用注解配置Spring AOP
在xml配置文件中初始化IoC容器,定义扫描注解的范围和启动Spring AOP注解模式。
<!--在IoC容器初始化时自动扫面四种组件类型注解并完成实例化
@Controller 当前mcv 控制类
@Repository 业务类 dao层 持久层
@Service 服务类
@Component 可以控制所有 不然确定的时候使用它就得了
-->
<context:component-scan base-package="top.xiongmingcai"/><!--定义扫描注解作用范围-->
<!--启动AOP注解模式-->
<aop:aspectj-autoproxy/>
既然AOP采用注解,则IoC也采用注解开发,给对应的Dao标记@Repository,对应的Service标记@Service,给对应的注入标记@Resource(这里可以注入在属性上,也可以注入在set方法上)。
然后给切面类进行Aop注解的标记:
@Component //标记当前类为组件
@Aspect //说明点前类是切面类
public class MethodChecker {
//ProceedingJoinPoint 是JoinPoint 升级版
@Around("execution( public * top.xiongmingcai..*.*(..)))")
public Object check(ProceedingJoinPoint pjp) throws Throwable {
Object ret;
try {
long startingTime = new Date().getTime();
//获得目标函数执行返回值
//控制目标方法是否执行
ret = pjp.proceed();
long endTime = new Date().getTime();
long duration = endTime - startingTime;
if (duration >= 1000) {
String targetClassName = pjp.getTarget().getClass().getName();
String targetMethodName = pjp.getSignature().getName();
SimpleDateFormat sdf = new SimpleDateFormat();
String now = sdf.format(new Date());
System.out.println("---->" + now + ":" + targetClassName + "." + targetMethodName + "用时:" + duration);
}
} catch (Throwable throwable) {
System.out.println("Exception message = " + throwable.getMessage()); //捕获异常
throw throwable;
}
return ret;
}
}
@Component //标记当前类为组件
@Aspect //说明点前类是切面类
//切面类
public class MethodAspect {
//切面方法,用于扩展额外功能
//JoinPoint 连接点 通过连接点可以获取目标类/方法的信息
@Before("execution(* top.xiongmingcai..*.*(..)))")
public void printExecutionTime(JoinPoint joinPoint) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String now = simpleDateFormat.format(new Date());
//获取目标类
String targetClassName = joinPoint.getTarget().getClass().getName();
//获取目标方法
String targetMethodName = joinPoint.getSignature().getName();
System.out.println("---->" + now + ":" + targetClassName + "." + targetMethodName);
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
System.out.println("--->参数 : " + arg);
}
}
@After("execution(* top.xiongmingcai..*.*(..)))")
public void doAfter(JoinPoint joinPoint) {
System.out.println("<----MethodAspect.doAfter");
}
@AfterReturning(pointcut="execution(* top.xiongmingcai..*.*(..)))", returning = "ret")
public void doAfterReturning(JoinPoint joinPoint ,Object ret){
System.out.println("返回后通知 <---" + ret);
}
@AfterThrowing(pointcut="execution(* top.xiongmingcai..*.*(..)))", throwing= "th")
public void doAfterThrowing(JoinPoint joinPoint,Throwable th){
System.out.println("异常通知 <---" + th);
}
}
- @AfterReturning - 如果方法返回成功,则将函数标记为在切入点覆盖的方法之前执行的通知。
- @Pointcut - 将函数标记为切入点
- @After - 将函数标记为在切入点覆盖的方法之后执行的通知。
- execution( expression ) - 涵盖应用通知的方法的表达式。
- throwing - 返回的异常名称。
- returning - 要返回的变量的名称
相关代码示例
https://github.com/MingCaiXiong/spring-learn/commit/b9e3c5505db4b7e74b656050b679eed6f7603368