layout: post title: "Spring面向切面编程" categories: Spring tags: AOP
Spring的面向切面编程可以完美解决。面向切面编程指的是在原来代码的基础上,加上增强的部分,生成一个代理的对象,也就是说,程序员可以在不修改源代码的情况下,实现对目标类的增强,其原理就是将一个被AOP动态增强的类,通过Java动态代理模式生成一个代理类。
"execution(* cn.youyinian.controller.v1.*.*(..))"
@Aspect
public class LogAspect {
@Before("execution(* cn.youyinian.test.*.*(..))")
publc void doBefore() {
System.out.println("test before");
}
}
用于目标方法被调用前做一些增强处理。
@Aspect
public class LogAspect {
@AfterReturning(returning="rvt", pointcut="execution(* cn.youyinian.test.*.*(..))")
publc void doAfterReturning(Object rvt) {
System.out.println("获取返回值:" + rvt);
}
}
用于访问目标方法返回值,并作相关处理。
@Aspect
public class LogAspect {
@After("execution(* cn.youyinian.test.*.*(..))")
publc void doAfter() {
System.out.println("test after");
}
}
用于目标方法被调用后做一些增强处理。与AfterReturning有些相似,但是也有区别,AfterReturning只有在目标方法成功完成后才会被织入。
@Aspect
public class LogAspect {
@Around("execution(* cn.youyinian.test.*.*(..))")
publc void doAround(ProceedingJoinPoint pjp) {
System.out.println("around before");
pjp.proceed();
System.out.println("around after");
}
}
ProceedingJoinPoint 参数是必须的,因为要使的目标方法要调用,那么必须调用其方法proceed()。
@Aspect
public class LogAspect {
@AfterThrowing(throwing="ex", pointcut="execution(* cn.youyinian.test.*.*(..))")
publc void doThrowing(Throwable ex) {
System.out.println("目标方法抛出异常:" + ex);
}
}
用于处理目标方法抛出的异常。
定义一个切面:
@Aspect
public class LogInterceptor {
// 定义一个切入点
@Pointcut("execution(* cn.youyinian.handler.*(..))")
private void log() {}
// before增强
@Before("log() && args(params)")
private void before(String params) {
XxlJobLogger.log("[定时任务] " + params + " >>>>>>>>>>>>>>>>>>> 开始");
}
// After增强
@After("log() && args(params)")
private void after(String params) {
XxlJobLogger.log("[定时任务] " + params + " >>>>>>>>>>>>>>>>>>> 结束");
}
}
目标方法:
package cn.youyinian.handler.topic;
import cn.youyinian.remote.TopicRemoteService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHander;
import com.xxl.job.core.log.XxlJobLogger;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* Created by zch on 2017/8/25.
*/
@JobHander(value="pushAuthHandler")
@Service
public class PushAuthHandler extends IJobHandler {
@Resource
private TopicRemoteService topicRemoteService;
@Override
public ReturnT<String> execute(String... params) throws Exception {
topicRemoteService.pushAuthMessage();
return ReturnT.SUCCESS;
}
}
定义一个切面:
@Aspect
public class TaskLockAspect {
// 此处省略部分代码
@Pointcut("@annotation(cn.youyinian.annotation.LockMethod)")
public void pointCut() {
}
@Around("pointCut()")
public Object doAround(ProceedingJoinPoint pjp) {
String targetName = pjp.getTarget().getClass().getName();
String methodName = pjp.getSignature().getName();
String lockKey = targetName + "#" + methodName;
if(!publicLock.getLock(lockKey)) {
Long time = Long.valueOf(valueRedisTemplate.get(lockKey));
logger.info("任务已被锁定lockKey:{}, 锁定时间:{}", lockKey, DateUtil.format(new Date(time), "yyyy-MM-dd HH:mm:ss"));
return null;
}
try {
Object result = pjp.proceed();
publicLock.releaseLock(lockKey);
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
publicLock.releaseLock(lockKey);
}
return null;
}
}
目标方法:
package cn.youyinian.controller.v1.remote;
// 此处省略部分代码
@RestController
@RequestMapping("/remote/topic")
public class TopicRemoteController {
private final Logger logger = LoggerFactory.getLogger(TopicRemoteController.class);
@Resource
private TopicAuthService topicAuthService;
@LockMethod
@RequestMapping(method = RequestMethod.GET, value = "task/pushAuthMessage")
public void pushAuthMessage() {
topicAuthService.pushAuthMessage();
}
}