上一节分析到创建代理
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
createProxy方法的最后一行代码
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
createAopProxy方法决定使用JDK代理还是Cglib代理
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 1.config.isProxyTargetClass()的判断
//ConfigurationClassPostProcessor#enhanceConfigurationClasses中configBeanDefs为完
//全配置类的集合(@Configuration标注的类),遍历configBeanDefs执行
//beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, //Boolean.TRUE);代码,在AutoProxyUtils#shouldProxyTargetClass方法中获取,返回true
//返回true的话在AbstractAutoProxyCreator#createProxy 方法中执行//proxyFactory.setProxyTargetClass(true);
//简单总结当标注@Configuration类config.isProxyTargetClass()返回true
//@EnableAspectJAutoProxy(proxyTargetClass=true)所有的类都返回true
// 2.hasNoUserSuppliedProxyInterfaces 类实现了接口,实现则返回true
if (!IN_NATIVE_IMAGE &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
//如果类为接口或者是Proxy类
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
决定使用哪种动态代理,继续调用createAopProxy().getProxy(classLoader);
首先分析JdkDynamicAopProxy动态代理,代理很简单
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
//JDK的动态代理,这里要注意的是入参为this,就是方法在执行的时候需要调用本类的
//(JdkDynamicAopProxy) invoke方法
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
Invoke方法 分析多个Advice的调用链
Invoke的关键代码
//通过方法名称获取Advice
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//为了调用链实例化ReflectiveMethodInvocation
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 调用链的开始
retVal = invocation.proceed();
retVal为ReflectiveMethodInvocation
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//如果调用链结束,则调用实际的方法
return invokeJoinpoint();
}
// interceptorsAndDynamicMethodMatchers 要调用实际方法所要经历的拦截器集合是List //++this.currentInterceptorIndex每调用一次索引加一
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
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 {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
//传的this,这是链路的关键, interceptorOrInterceptionAdvice的invoke都会调用
// invocation.proceed();方法,那有回调了这个方法,形成链路
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
interceptorsAndDynamicMethodMatchers的集合,我们先不关心第一个,仔细看顺序,
MethodBeforeAdviceInterceptor
AspectJAfterAdvice
AspectJAfterThrowingAdvice
在以前的版本,顺序是调过来了,
AspectJAfterThrowingAdvice
AspectJAfterAdvice
MethodBeforeAdviceInterceptor
(没有实际验证过只是相关的文章),两个版本的区别,我认为老版本
AspectJAfterThrowingAdvice把所有方法都trycatch了,也就是AspectJAfterAdvice和MethodBeforeAdviceInterceptor的异常也捕获了,而这个版本,只捕获了实际调用方法的异常
[图片上传失败...(image-ee5114-1632043197037)]
MethodBeforeAdviceInterceptor
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
//实际方法之前调用before方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//上面说过,因为传的是this那mi就为ReflectiveMethodInvocation,回调了proeed方法
return mi.proceed();
}
AspectJAfterAdvice
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//继续回调
return mi.proceed();
}
//在finally中执行后置通知
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
AspectJAfterThrowingAdvice
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//因为这里AspectJAfterThrowingAdvice为最后一个Advice,再执行mi.proceed()判断是最后//,就会调用实际方法,也就是AspectJAfterThrowingAdvice只捕获了实际方法的异常,是否还//AspectJAfterAdvice方法是再finally中,就算发生异常也一定会执行,
//通知当然也会执行
return mi.proceed();
}
catch (Throwable ex) {
//当实际调用的方法发生异常的时候,调用invokeAdviceMethod方法,
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
ObjenesisCglibAopProxy代理,相比较复杂一点
首先举个例子Enhancer增强类
public class MyMethodIntercpetor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println ("MyMethodIntercpetor拦截器---方法执行之前---拦截的是Hello的sayHello方法");
Object invoke = methodProxy.invokeSuper (o, objects);
System.out.println ("MyMethodIntercpetor拦截器---方法执行之后---拦截的是Hello的sayHello方法");
return invoke;
}
public static void main(String[] args) {
System.setProperty (DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\cglib");
Enhancer enhancer = new Enhancer ();
enhancer.setSuperclass (Hello.class);
MyMethodIntercpetor myMethodIntercpetor = new MyMethodIntercpetor ();
HelloMethodIntercpetor helloMethodIntercpetor = new HelloMethodIntercpetor ();
//设置callback数组是需要设置filter,调用方法时,判断使用哪个拦截器,CallbackFilter的
//accept方法返回的时数组的下角标,这是在创建代理类的时候就规定好具体使用哪个//Interceptor,
Callback[] callback = new Callback[]{myMethodIntercpetor, helloMethodIntercpetor};
enhancer.setCallbacks (callback);
enhancer.setCallbackFilter (new CallbackFilterImpl ());
//如果时单个callback不需要filter
Hello hello = ( Hello ) enhancer.create ();
hello.sayHello ();
}
}
class Hello {
public void sayHello() {
System.out.println ("sayHello");
}
public void sayWorld() {
System.out.println ("sayWorld");
}
}
class HelloMethodIntercpetor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println ("HelloMethodIntercpetor拦截器---方法执行之前");
Object invoke = methodProxy.invokeSuper (o, objects);
System.out.println ("HelloMethodIntercpetor拦截器---方法执行之后");
return invoke;
}
}
class CallbackFilterImpl implements CallbackFilter {
@Override
public int accept(Method method) {
//因为有两个callback,当调用sayHello方法的是,return 0 会调用第一个callback,这是再增强类的时候就已经定好了,而不是再调用sayHello方法的时候,在到这里判断调用那个callback
if (method.getName ().equals ("sayHello")) {
return 0;
} else {
return 1;
}
}
}
那ObjenesisCglibAopProxy的getProxy方法也是类似的
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
//因为rootClass可能是被@Configuration标注,就是本身已经是增强类了,这里我们获取了原始类
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
//获取了callbacks,这里我们只关注数组的第一个Callback DynamicAdvisedInterceptor
//因为在下面的setCallbackFilter方法中,都返回了0,其余的我也没有研究过
//也就是实际要调用的方法,都会走DynamicAdvisedInterceptor的intercept方法
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
DynamicAdvisedInterceptor的intercept方法和Jdk动态代理是一样的,利用调用链完成拦截功能.
Intercept方法
主要方法,就是下面的方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
点进去proceed方法,发现了supper.proceed()再点进去发现依然调用的是
ReflectiveMethodInvocation的proceed方法,就和上面介绍的jdk动态代理执行调用链一致了,这里就不介绍了.
网友评论