1、Component
放在类上的注解,将此类实例化到spring容器当中。可以在别的service这样的类中能够注入该类并使用。
@Component
public class ProjectUrlConfig {
}
@Service
public class PushMessageImpl implements PushMessageService {
@Autowired
private ProjectUrlConfig projectUrlConfig;
}
2、Aspect
切面。
AOP这里需要注意的是:
(1) execution表达式
(2) Spring AOP不进入before和业务方法,却进入其他切面的问题。原因:没写环绕通知进程方法
(3) 单个方法被多个Aspect方法拦截的顺序问题
(4) Spring AOP不进入afterThrowing方法问题。原因:around方法没抛出异常
以下代码基于spring boot
@Aspect
@Component
public class GameAspect {
private final static Logger logger = LoggerFactory.getLogger(GameAspect.class);
@Pointcut("execution(public * com.tianci.controller.GameController.*(..))")
public void game() {}
@Before("game()")
public void doBefore(JoinPoint joinPoint) {
logger.info("before");
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes != null ? servletRequestAttributes.getRequest() : null;
//url
logger.info("url={}", request != null ? request.getRequestURL() : null);
//method
logger.info("method={}", request != null ? request.getMethod() : null);
//ip
logger.info("ip={}", request != null ? request.getRemoteAddr() : null);
//类方法
logger.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
//参数
logger.info("args={}", joinPoint.getArgs());
}
@After("game()")
public void doAfter() {
logger.info("after");
}
@AfterReturning("game()")
public void doAfterReturning() {
logger.info("afterReturning");
}
@AfterThrowing("game()")
public void doAfterThrowing() {
logger.info("afterThrowing");
}
@Around("game()")
public void around(JoinPoint joinPoint) {
logger.info("around前");
ProceedingJoinPoint proceedingJoinPoint = (ProceedingJoinPoint)joinPoint;
try {
Object obejct = proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
logger.info("around后");
}
}
package com.tianci.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Create by tianci
* 2019/2/13 14:34
*/
@RestController
public class GameController {
private final static Logger logger = LoggerFactory.getLogger(GameController.class);
@GetMapping("/doGame")
public void doGame() {
logger.info("sing...");
}
}
运行结果:
: around前
: before
//////////////////////////////////参数部分
: url=http://localhost:8080/doGame
: method=GET
: ip=0:0:0:0:0:0:0:1
: class_method=com.tianci.controller.GameController.doGame
: args={}
////////////////////////////////////////
: sing...
: around后
: after
: afterReturning
以上是正确运行的结果,接下来演示抛出异常的运行结果。
这时候就有问题了。
将测试类改成
package com.tianci.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Create by tianci
* 2019/2/13 14:34
*/
@RestController
public class GameController {
private final static Logger logger = LoggerFactory.getLogger(GameController.class);
@GetMapping("/doGame")
public void doGame() {
throw new IllegalArgumentException("异常");
//logger.info("sing");
}
}
发现并没有执行 afterThrowing() 方法。
开始找问题,这个问题网上查了好久,但都没有解决,但是却有成功执行afterThrowing()的例子,一步一步的查找异同。发现了问题所在。
原因在于:
切面的around方法中把异常catch掉了,应该在方法上 throws Throwable
于是将around方法改为(当然注释掉around方法也可以解决这个问题):
@Around("game()")
public void around(JoinPoint joinPoint) throws Throwable {
logger.info("around前");
ProceedingJoinPoint proceedingJoinPoint = (ProceedingJoinPoint)joinPoint;
Object obejct = proceedingJoinPoint.proceed();
logger.info("around后");
}
说下单个方法被多个Aspect方法拦截的顺序问题,order注解可以解决,值越小,优先级越高
@Order(1)
@Aspect
@Component
public class GameAspect {}
网友评论