Spring AOP源码分析
1、AOP的应用场景
- 日志记录
- 权限验证
- 效率检查
- 事务管理
2、Spring AOP
-
jdk代理
Java动态代理是基于接口的, -
cglib代理
CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,
它允许我们在运行时对字节码进行修改和动态生成
CGLIB通过继承的方式进行代理,无论目标对象有没有实现接口都可以代理,
但是无法处理final的情况。 -
第三方的aspecj(需要单独导入依赖)
aop自定义注解
定义注解,扫描注解,执行逻辑
1、元注解
- @Target
- @Retention
- @Documented
- @Inherited
@Target注解主要用于定义注解使用的位置,被描述的注解可以用在什么地方 。@Target的参数是ElementType枚举类,下面详解都有什么作用。
@Retention注解的作用就是指定注解的生命周期。比如在编译时可以处理运行时可以处理等。它的枚举类为RetentionPolicy
@Documented注解的话就比较简单,主要作用就是描述注解文档化。就是在 在生成javadoc的时候,是不包含注释的,但是如果注解被@Documented修饰,则生成的文档就包含该注解。此注解在以后版本可能会被删除这里就不详细的看了。
@Inherited 注解修饰的注解时具有可继承性的,就是说我们用 @Inherited 修饰了一个类,那么这个类的子类也会默认继承此注解。
@Aspect
@Component
public class RpcExceptionAspect {
private final static Logger logger = LoggerFactory.getLogger(RpcExceptionAspect.class);
@Pointcut("execution(public * com.lucky.xray.cases.service.impl.*.*(..))")
public void webPointcut() {
}
/**
* rpc服务不存在或未注册时抛出异常处理
* @param joinPoint
* @param ex
*/
@AfterThrowing(value = "webPointcut()", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
StringBuilder param = new StringBuilder();
for(Object arg:joinPoint.getArgs()){
param.append(arg.toString()).append(",");
}
logger.error("rpc调用异常接口:{}.{}, 参数:{}", className, methodName, param);
if (ex instanceof RpcException) {
// rpc调用异常
throw new RpcException("rpc接口调用异常:" + methodName, ex);
}
throw new RpcException("远程调用未知异常", ex);
}
}