Aop:在原有功能不变的基础上, 进行功能增强,比如在方法发生异常/方法发生之前/之后进行额外逻辑的插入。这样隐式横向插入逻辑的动作被我们称为Aop。
在Spring中,我们都是将对象交给singletonObjects单例池管理,在使用这个对象之前,就已经生成了对应的Bean。Spring在AspectJ的基础上,进行了封装(就是直接把AspectJ的代码抄了一下),形成了Spring-Aop,让我们可以在原有功能的基础上,进行额外的逻辑增强(代理模式),就是我放到Spring中的Bean,其实不是我认为的Bean,而是生成了一个代理对象来代理这个Bean伪代码如下
java
try{
proxy extends target//代理对象继承自被代理对象
methodBeforeAround(proxy)//方法执行环绕前
methodBefore(proxy)//方法执行前
method.invoke(proxy)//被代理对象执行
methodAfterAround(proxy)//方法执行环绕后
}
catch(Throwable e){
exceptionMethod(proxy);//出异常的时候执行
throw e;
}
finally{
methodAfter(proxy);//方法执行完之后
}
我们可以对方法执行前后的各个点进行一个额外逻辑的插入,对原有方法进行功能增强。然后在Bean的生命周期中对target(被代理对象)额外生成一个代理对象,将其放到单例池中,然后在使用的时候将该代理对象依赖注入到对应的属性中用于替代target对象。
java中的Demo实现代码如下
java
public static void main(String[] args) {
UserService userService = new UserService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.addAdvice(new MyBeforeAdvice());
//对UserService的test方法进行前置增强
UserService proxy = (UserService) proxyFactory.getProxy();
proxy.test();
}
public class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("方法执行前执行");
}
}
//print: 方法执行前执行
//print: 方法test执行
上述Demo我们对UserService进行了一个前置的代理增强, 可以看到前置处理就是实现了一个MethodBeforeAdvice,那么其他额外功能的插入点,也有对应的Advice接口
AfterReturningAdvice:方法return后执行
MethodInterceptor:围绕方法前后都可以自行实现,需要手动调用proceed方法
ThrowsAdvice:出异常之后执行,这个需要自己手写afterThrowing方法
MethodBeforeAdvice:方法执行前执行
上述就是Spring-Aop提供给我们的Advice,用于额外功能点的增强。这些Advice最后都会被转成MethodInterceptor 。其实还有一种afterAdvice,就是不管有没有异常,都会在最后执行,finally机制,但是spring-Aop提供给我们的接口(AfterAdvice)中并没有对应的实现类,但是Aspectj中有对应的实现类AspectJAfterAdvice
在Spring中我们通常使用Jdk代理和Cglib代理来生成代理对象,我们先来看一下Cglib动态代理方法执行时的核心源码
获取代理对象CglibAopProxy.getProxy()->只提取核心代码
java
public Object getProxy(@Nullable ClassLoader classLoader) {
//获取被代理的类
Class<?> rootClass = this.advised.getTargetClass();
//创建用于生成代理对象的工具
Enhancer enhancer = createEnhancer();
// 将代理类的父类设置成被代理类
enhancer.setSuperclass(proxySuperClass);
// 代理类额外要实现的接口
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
//这是最核心的源码,获取Spring中匹配的Advisor,后续章节会讲到
//也是这一步将Advisor转换成了MethodInterceptor
Callback[] callbacks = getCallbacks(rootClass);
//返回代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}
**执行逻辑(额外逻辑的执行)**CglibAopProxy.proceed()->ReflectiveMethodInvocation.proceed()
java
public Object proceed() throws Throwable {
//interceptorsAndDynamicMethodMatchers:
// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1,然后接着会递归走到这里,就是一个简单的执行链
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//最后一个interceptor执行完后就会执行被代理方法
return invokeJoinpoint();
}
// 每次递归之后currentInterceptorIndex就++
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
// 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 动态匹配,根据方法参数匹配
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 不匹配则执行下一个MethodInterceptor
return proceed();
}
}
else {
// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归
// 比如MethodBeforeAdviceInterceptor
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
在执行对应的方法的时候,会对传入进来的Interceptor链进行一个操作(递归执行)(这条链其实就是找到的Advisor转换成的MethodInterceptor,在getCallBacks中会转 ),初始值currentInterceptorIndex为-1,然后每次执行的时候就++,观察是否到达了对应的链Size,如果是,那么代表对应的代理逻辑已经被执行完,该执行被代理方法了,后面有一个判断是否是动态的MethodMatcher(关于Matcher,Spring-Aop源码解析(中)会解析),下面代码也是对其进行的一个简要分析。如果满足了对应的matcher匹配,那么就会执行对应的链路中的额外逻辑(这里面会自动调用proceed方法),如果不满足,那么直接递归,观察下一个MethodInterceptor是否满足(不断的递归)
java
proxyFactory.addAdvisor(new PointcutAdvisor() {
@Override
public Pointcut getPointcut() {
return new Pointcut() {
@Override
public ClassFilter getClassFilter() {
//先匹配类
return null;
}
@Override
public MethodMatcher getMethodMatcher() {
//再匹配方法
new MethodMatcher() {
@Override
public boolean matches(Method method, Class<?> targetClass) {
return false;
}
@Override
public boolean isRuntime() {
//如果runTime设置成true,那么下面的matches会生效
//进行额外方法中的参数是否匹配
//也就是转换成了上面我们讲的InterceptorAndDynamicMethodMatcher
return false;
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
return false;
}
}
}
};
}
});
在匹配对应的Advisor是否匹配当前正在执行的方法的时候,会先根据Class做匹配,观察类是否相等,然后对方法进行一个匹配,观察方法是否相等,第三道过滤必须将MethodMatcher中的Runtime属性设置成true,才会转换成InterceptorAndDynamicMethodMatcher,就是会进一步对方法中的参数进行一个额外的判断,观察参数是否也是匹配的