Spring AOP使用与原理
创始人
2024-02-03 15:45:37
0

AOP介绍

SpringAOP核心概念
上述中已经出现的关键词有Advice(顶级的通知类/拦截器)、MethodInvocation(方法连接点)、MethodInterceptor(方法拦截器)
SpringAOP在此基础上又增加了几个类,丰富了AOP定义及使用概念,包括
Advisor:包含通知(拦截器),Spring内部使用的AOP顶级接口,还需要包含一个aop适用判断的过滤器,考虑到通用性,过滤规则由其子接口定义,例如IntroductionAdvisor和PointcutAdvisor,过滤器用于判断bean是否需要被代理
Pointcut: 切点,属于过滤器的一种实现,匹配过滤哪些类哪些方法需要被切面处理,包含一个ClassFilter和一个MethodMatcher,使用PointcutAdvisor定义时需要
ClassFilter:限制切入点或引入点与给定目标类集的匹配的筛选器,属于过滤器的一种实现。过滤筛选合适的类,有些类不需要被处理
MethodMatcher:方法匹配器,定义方法匹配规则,属于过滤器的一种实现,哪些方法需要使用AOP

AOP使用方法

配置Advisor

这一步对SpringAOP使用者很关键,决定了我们如何定义配置Advisor,即SpringAOP和Aspectj,实际使用配置AOP方式有多种,还区分xml和注解,最终转化处理时我认为只分为这两种。其中Aspectj方式配置AOP应该是最常见应用最广泛的用法了。

前面提到Aspectj是一种静态代理,而SpringAOP是动态代理。但Aspectj的一套定义AOP的API非常好,直观易用。所以Spring引入了Aspectj,但只使用部分注解用来定义配置AOP,在获取Advisor阶段用来生成Advisor,与后面的代理生成和代理增强执行无关!
最少需要定义三个类,一个Advisor的实现类,一个Advice实现类(拦截器),一个aop适配过滤器(这里使用的Advisor为派生的PointcutAdvisor ,需要定义PointCut切点)。可以增加一个注解用于AOP埋点,需要给bean哪个方法进行切面,则方法上加上该注解。
Advisor:MyAdvisor,返回一个Advice,
Advice:MyInterceptAdvice,拦截器,invoke方法中可以添加切面逻辑代码
PointCut: MyPointCut,切点,匹配过滤出需要切面的类及方法,查找方法头注解了MyAnnotation的方法。
埋点注解:MyAnnotation
MyAdvisor.java

@Component
public class MyAdvisor implements PointcutAdvisor {@Overridepublic Advice getAdvice() {return new MyInterceptAdvice();}@Overridepublic boolean isPerInstance() {return false;}@Overridepublic Pointcut getPointcut() {return new MyPointCut();}
}

MyInterceptAdvice.java

public class MyInterceptAdvice implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("go go go MyAdvisor process!!!");return invocation.proceed();}
}

MyPointCut.java

public class MyPointCut implements Pointcut {@Overridepublic ClassFilter getClassFilter() {return new MyClassFilter();}@Overridepublic MethodMatcher getMethodMatcher() {return new MyMethodMatcher();}private class MyMethodMatcher implements MethodMatcher {@Overridepublic boolean matches(Method method, Class targetClass) {Annotation[] annoArray = method.getDeclaredAnnotations();if (annoArray == null || annoArray.length == 0) {return false;}for (Annotation annotation : annoArray) {if (annotation.annotationType() == MyAnnotation.class) {return true;}}return false;}@Overridepublic boolean isRuntime() {return false;}@Overridepublic boolean matches(Method method, Class targetClass, Object... args) {return false;}}private class MyClassFilter implements ClassFilter {@Overridepublic boolean matches(Class clazz) {return AnnotationUtils.isCandidateClass(clazz, MyAnnotation.class);}}
}

再定义一个测试类

@Component
public class TestService {@MyAnnotationpublic void test() {System.out.println("test!");}
}

运行方法测试发现aop生效

使用Aspectj间接配置Advisor

一个类就可以了,定义切点和增强方法

@Aspect
@Component
public class AopConfig {@Pointcut("execution(* cn.nec.aop.cnnecaop.service.*.*(..))")public void pointCut() {}@Around("pointCut()")public Object around(ProceedingJoinPoint joinPoin) {System.out.println("go go go MyAspectJ process!!!");Object obj = null;try {obj = joinPoin.proceed();} catch (Throwable throwable) {throwable.printStackTrace();}return obj;}
}

注解的形式,实际上最终还是被封装成Advice接口

注解AOP的几个执行时机

  • @Before
    • 前置通知:目标方法之前执行
  • MethodBeforeAdviceInterceptor
@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());return mi.proceed();}
  • @After
    • 后置通知:目标方法之后执行(始终执行)
  • AspectJAfterAdvice
@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {try {return mi.proceed();}finally {invokeAdviceMethod(getJoinPointMatch(), null, null);}}
  • @AfterReturning
    • 返回通知:执行方法结束前执行(异常不执行)
    • AfterReturningAdviceInterceptor
	@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;}
  • @AfterThrowing
    • 异常通知:出现异常的时候执行
    • AspectJAfterThrowingAdvice
@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {try {return mi.proceed();}catch (Throwable ex) {if (shouldInvokeOnThrowing(ex)) {invokeAdviceMethod(getJoinPointMatch(), null, ex);}throw ex;}
  • @Around
    • 环绕通知:环绕目标方法执行(执行前后都在一个方法中自定义)
    • AspectJAroundAdvice
	@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {if (!(mi instanceof ProxyMethodInvocation)) {throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);}ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);JoinPointMatch jpm = getJoinPointMatch(pmi);return invokeAdviceMethod(pjp, jpm, null, null);}

around方法中,不会有自动执行process的逻辑。因此,需要在自己定义的方法中自行执行

AOP原理分析

AOP入口

SpringAOP是对bean的一种扩展,是后处理器的一种处理。Spring bean在 执行初始化方法前后,会使用所有BeanPostProcessor对bean进行特殊处理。Aop代理即是一种对bean特殊处理。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
} 

此时用于代理的BeanPostProcessor登场,对需要代理的bean进行代理
对应的BeanPostProcessor为AbstractAutoProxyCreator的子类,执行AbstractAutoProxyCreator.postProcessAfterInitialization()。

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyProxyReferences.remove(cacheKey) != bean) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;
}

earlyProxyReferences中存放的是循环依赖提前暴露bean生成的代理
注意!如果earlyProxyReferences已经存在了这个bean,代表该bean已经被提前暴露生成过了代理,那么不再进行重复代理!
紧接着进入wrapIfNecessary


/*** Wrap the given bean if necessary, i.e. if it is eligible for being proxied.* @param bean the raw bean instance* @param beanName the name of the bean* @param cacheKey the cache key for metadata access* @return a proxy wrapping the bean, or the raw bean instance as-is*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}//advisedBeans的对应value为fasle,则代表不需要代理if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}//对于本身就是advisorBean和需要跳过的bean不进行代理if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.// 获取拦截器,及Advisor,看样子也可以获取Advice!Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);// 生成代理对象Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;
}

可以看到代理生成分了两步,获取AdvicesAndAdvisors,然后生成代理对象
在这里插入图片描述
getAdvicesAndAdvisorsForBean方法

@Override@Nullableprotected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, @Nullable TargetSource targetSource) {List advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}
	protected List findEligibleAdvisors(Class beanClass, String beanName) {List candidateAdvisors = findCandidateAdvisors();List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}

获取所有的Advisor

findCandidateAdvisors用于获取所有的Advisor,默认获取直接配置的Advisor。即实现了Advisor的所有bean。

advisors.add(this.beanFactory.getBean(name, Advisor.class));

AnnotationAwareAspectJAutoProxyCreator重写了findCandidateAdvisors,不仅可以获取直接配置得Advisor,还可以获取用AspectJ间接定义的Advisor,即把AspectJ定义的bean转化为Advisor。
所以使用AnnotationAwareAspectJAutoProxyCreator可以同时支持两种配置AOP方式!

获取AspectJ注解间接定义的Advisor

if (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);AspectMetadata amd = new AspectMetadata(beanType, beanName);if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {MetadataAwareAspectInstanceFactory factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);List classAdvisors = this.advisorFactory.getAdvisors(factory);if (this.beanFactory.isSingleton(beanName)) {this.advisorsCache.put(beanName, classAdvisors);}else {this.aspectFactoryCache.put(beanName, factory);}advisors.addAll(classAdvisors);}else {// Per target or per this.if (this.beanFactory.isSingleton(beanName)) {throw new IllegalArgumentException("Bean with name '" + beanName +"' is a singleton, but aspect instantiation model is not singleton");}MetadataAwareAspectInstanceFactory factory =new PrototypeAspectInstanceFactory(this.beanFactory, beanName);this.aspectFactoryCache.put(beanName, factory);advisors.addAll(this.advisorFactory.getAdvisors(factory));}}
}

查找过滤合适的Advisor

findAdvisorsThatCanApply用于查找可用的Advisor,遍历所有的Advisor,使用Advisor的PointCut执行匹配方法,对bean Class的方法挨个进行匹配,能匹配到说明该Advisor合格,加入到返回结果中,这里只展示了其中一种切点的处理逻辑–PointcutAdvisor。

public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");if (!pc.getClassFilter().matches(targetClass)) {return false;}MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}Set> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));for (Class clazz : classes) {Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {if (introductionAwareMethodMatcher != null ?introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :methodMatcher.matches(method, targetClass)) {return true;}}}return false;
}

分别根据每个advisor pointCut的classFilter和MyMethodMatcher进行匹配。

过滤规则扩展

直接实现Advisor,和实现Advisor的扩展接口有什么区别?
Advisor是顶级接口,其实器残缺的,没有给出过滤匹配的方式
扩展接口IntroductionAdvisor和PointcutAdvisor。

Advisor没有过滤匹配规则,会匹配所有bean(不包含特殊bean)
IntroductionAdvisor给出了class类型过滤方式,会匹配限定类型的bean
PointcutAdvisor给出了class类型+方法匹配过滤方式,会匹配限定类型限定方法的bean。

显然PointcutAdvisor功能最强大,适用性和实用性最强

public static boolean canApply(Advisor advisor, Class targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}else if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor) advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {// It doesn't have a pointcut so we assume it applies.return true;}
}

对于Aspect扩展

	extendAdvisors(eligibleAdvisors);
@Overrideprotected void extendAdvisors(List candidateAdvisors) {AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);}
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List advisors) {// Don't add advisors to an empty list; may indicate that proxying is just not requiredif (!advisors.isEmpty()) {boolean foundAspectJAdvice = false;for (Advisor advisor : advisors) {// Be careful not to get the Advice without a guard, as this might eagerly// instantiate a non-singleton AspectJ aspect...if (isAspectJAdvice(advisor)) {foundAspectJAdvice = true;break;}}if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {advisors.add(0, ExposeInvocationInterceptor.ADVISOR);return true;}}return false;
}

如果是sAspectJAdvice,那么添加一个advisor,ExposeInvocationInterceptor这个的用处后面看

生成代理对象及代理执行

使用可用的Advisor和当前bean对象生成动态代理对象

	if (specificInterceptors != DO_NOT_PROXY) {//代码当前bean被代理this.advisedBeans.put(cacheKey, Boolean.TRUE);Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}
ProxyFactory proxyFactory = new ProxyFactory();
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.getProxy(getProxyClassLoader());createAopProxy().getProxy(classLoader);

createAopProxy用于创建代理类,进入源码可以看到支持两种代理方式,其中JDK动态代理需要bean实现接口。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (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.");}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}
}

注意这里有有个坑,不能仅仅看类是否有继承接口,还要看一个配置
proxyTargetClass
true
目标对象实现了接口 – 使用CGLIB代理机制
目标对象没有接口(只有实现类) – 使用CGLIB代理机制
false
目标对象实现了接口 – 使用JDK动态代理机制(代理所有实现了的接口)
目标对象没有接口(只有实现类) – 使用CGLIB代理机制
在这里插入图片描述

可见如果proxyTargetClass是true,那么不管什么类都会使用cglib代理,只有目标类本身就接口/代理类才会使用jdk代理
在这里插入图片描述

JDK动态代理

public Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());}Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

是不是熟悉了,和手动定义JDK动态代理一样,对于jdk动态代理的拦截器InvocationHandler就是其本身
核心就是
Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, invocationHandler)。
再来看看核心方法invoke

// Get the interception chain for this method.
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {// We can skip creating a MethodInvocation: just invoke the target directly// Note that the final invoker must be an InvokerInterceptor so we know it does// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {// We need to create a method invocation...MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// Proceed to the joinpoint through the interceptor chain.retVal = invocation.proceed();
} 

从Advisor中获取拦截器,然后生成一个连接点(ReflectiveMethodInvocation),包含链接器和代理信息,执行连接点的proceed方法,会链式调用拦截器,执行所有的切面代码。

public Object proceed() throws Throwable {// We start with an index of -1 and increment early.if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}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.return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}
}
 @Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("go go go MyAdvisor process!!!");return invocation.proceed();}

切面执行完毕后会继续调用ReflectiveMethodInvocation的invoke方法,currentInterceptorIndex自增,执行匹配到的Advice,执行完毕执行invokeJoinpoint方法

注意点

jdk代理是对接口做的代理,匹配advice时,时根据接口
例如根据注解匹配,注解值放在子类上时无效的,需要放到接口上
例如

public interface ITestService {@MyAnnotationvoid test();
}

ExposeInvocationInterceptor的作用是什么

我们前面知道了,如果有注解间接定义的advisor,那么会添加一个ExposeInvocationInterceptor到首位
第一个执行的拦截器就会是ExposeInvocationInterceptor
从英文名字,顾名思义,暴露调用器的拦截器。
其就是起了暴露一个调用器作用的拦截器。
1、那么其暴露了什么调用器?
2、是如何暴露的,通过什么方法实现?
3、暴露给谁?
4、在什么时候起到拦截作用?
调用链首先调用此ExposeInvocationInterceptor拦截器的invoke方法,将MethodInvocation mi 设置到
ThreadLocal invocation 里面

@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {MethodInvocation oldInvocation = invocation.get();invocation.set(mi);try {return mi.proceed();}finally {invocation.set(oldInvocation);}}

至于为什么要把MethodInvocation塞到threadLocal中 invocation中
是因为通过注解@Aspectj定义的advise执行时,其对应的接口没有MethodInvocation这个参数
例如前置执行器

@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());return mi.proceed();}
	void before(Method method, Object[] args, @Nullable Object target) throws Throwable;

但是又需要使用,因此需要使用threadLocal进行传递

@Overridepublic void before(Method method, Object[] args, @Nullable Object target) throws Throwable {invokeAdviceMethod(getJoinPointMatch(), null, null);}
@Nullableprotected JoinPointMatch getJoinPointMatch() {MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();if (!(mi instanceof ProxyMethodInvocation)) {throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);}return getJoinPointMatch((ProxyMethodInvocation) mi);}

那么获取joinpoint是为了干什么
例如有一个前置执行方法

  @Before(value = "execution(public * test(int)) && args(a)")public void before(JoinPoint joinPoint,int a){System.out.println("------------------hello 方法执行前-------------------");}

需要传参,joinPoint就是从MethodInvocation中获取

CGLIB动态代理类

	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));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 aboveenhancer.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);

与jdk自然不同,用的是cglib创建代理的方式
生效的callback可能有多个,这里看 DynamicUnadvisedInterceptor

	@Override@Nullablepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;TargetSource targetSource = this.advised.getTargetSource();try {if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...target = targetSource.getTarget();Class targetClass = (target != null ? target.getClass() : null);List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {// We can skip creating a MethodInvocation: just invoke the target directly.// Note that the final invoker must be an InvokerInterceptor, so we know// it does nothing but a reflective operation on the target, and no hot// swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = methodProxy.invoke(target, argsToUse);}else {// We need to create a method invocation...retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}}
 

执行proceed的流程与jdk的流程基本相同。
执行时生成的连接点为CglibMethodInvocation,是JDK动态代理连接点ReflectiveMethodInvocation的子类,执行的还是ReflectiveMethodInvocation的proceed方法

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...