这里以
配置文件(UserAOPTest-context.xml)信息:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
class="org.springframework.context.support.learning.aop.UserImpl"/>
class="org.springframework.context.support.learning.aop.UserAspect"/>
class="false"/>
View Code
测试用例代码:
public class UserAOPTest {
@Test
void aopTestWithJDK(){
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(getClass(), "UserAOPTest-context.xml");
User user = ctx.getBean(User.class);
user.doTask();
}
}
View Code
代码:User
public interface User {
String doTask();
}
View Code
代码:UserImpl
public class UserImpl implements User{
@Override
public String doTask() {
System.out.println(getClass().toString() + " doTask...");
return "return doTask";
}
}
View Code
代码:UserAspect
@Aspect
public class UserAspect {
/** Logger used by this class. Available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
@Pointcut("execution(public * org.springframework.context.support.learning.aop.User.doTask(..))")
public void pointCut(){}
@Before("pointCut()")
public void before(JoinPoint point) throws Throwable {
Signature signature = point.getSignature();
if (logger.isInfoEnabled()) {
logger.info("before --> begin Time:" + System.currentTimeMillis());
}
}
@After("pointCut()")
public void after(JoinPoint point) throws Throwable {
Signature signature = point.getSignature();
if (logger.isInfoEnabled()) {
logger.info("after --> begin Time:" + System.currentTimeMillis());
}
}
@AfterReturning(pointcut="pointCut()", returning="returnValue")
public void afterReturning(JoinPoint point, Object returnValue) throws Throwable {
Signature signature = point.getSignature();
if (logger.isInfoEnabled()) {
logger.info("afterReturning --> begin Time:" + System.currentTimeMillis());
}
}
@Around("pointCut()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
Signature signature = pjp.getSignature();
if (logger.isInfoEnabled()) {
logger.info("around --> begin Time:" + System.currentTimeMillis());
}
pjp.proceed();
if (logger.isInfoEnabled()) {
logger.info("around --> end Time:" + System.currentTimeMillis());
}
}
@AfterThrowing(throwing="ex", pointcut="pointCut()")
public void afterThrowing(Throwable ex) {
if (logger.isInfoEnabled()) {
logger.info("目标方法中抛出的异常:" + ex);
logger.info("afterThrowing --> end Time:" + System.currentTimeMillis());
}
}
}
View Code
一.读取AOP配置,并根据AOP配置进心初始化
XmlBeanDefinitionReader#registerBeanDefinitions()
XmlBeanDefinitionReader#createReaderContext()
XmlBeanDefinitionReader#getNamespaceHandlerResolver()
XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver()
1.读取XML配置文件时,创建默认 DefaultNamespaceHandlerResolver 实例,准备解析XML配置文件信息。
- 依次循环解析
(在 DefaultNamespaceHandlerResolver#getHandlerMappings() 中读取META-INF/spring.handlers配置文件。)
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
- 具体解析器进行处理。
BeanDefinitionParserDelegate#parseCustomElement(Element, BeanDefinition)
/**
* Parse a custom element (outside of the default namespace).
* @param ele the element to parse
* @param containingBd the containing bean definition (if any)
* @return the resulting bean definition
*/
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
View Code
- 解析器初始化。
AopNamespaceHandler#init()
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
* and '{@code scoped-proxy}' tags.
*/
@Override
public void init() {
// In 2.0 XSD as well as in 2.5+ XSDs
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace in 2.5+
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
View Code
- 具体配置依次分析:
ConfigBeanDefinitionParser
returning="returnValue">
throwing="ex">
View Code
AspectJAutoProxyBeanDefinitionParser
AspectJAutoProxyBeanDefinitionParser#parse
AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()
AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry, Object)
registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source)
ScopedProxyBeanDefinitionDecorator
二. AOP创建AnnotationAwareAspectJAutoProxyCreator 实例
PostProcessorRegistrationDelegate#registerBeanPostProcessors(ConfigurableListableBeanFactory, AbstractApplicationContext)
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
循环注册 BeanPostProcessors 时,创建 AnnotationAwareAspectJAutoProxyCreator 实例,并添加到 BeanPostProcessor 列表。
AnnotationAwareAspectJAutoProxyCreator 实例初始化时,初始化,创建后期使用的辅助对象实例。
AnnotationAwareAspectJAutoProxyCreator#initBeanFactory()
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
View Code
三. 创建业务类实例,并根据切点配置创建代理对象
(一) 创建切面通知(Advice)实例 Advisor。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation()
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation()
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation()
org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip()
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors()
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors()
在创建对象实例之前,解析当前程序 @Aspect 标记的类信息 {Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class}。
- 获得当前 beanFactory 中配置的所有 beanNames 信息。
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false)
- 循环遍历处理 bean 配置。
a. 获得 beanName 对应的类型。
b. 判断 beanType 是否是 isAspect(beanType)。
c. 获取 beanName 对应的所有通知 ( Advice ) 包装列表 List
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors()
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisorMethods()
- 获取 aspectClass 所有方法(Method),并按 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class 进行排序。
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisor(Method, MetadataAwareAspectInstanceFactory , int , String)
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
View Code
1.创建方法切点信息实例。AspectJExpressionPointcut
-
创建通知和切点关联对象实例。 InstantiationModelAwarePointcutAdvisorImpl
-
最终保存在 org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#advisorsCache 实例中。
InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice()
ReflectiveAspectJAdvisorFactory#getAdvice()
(二). 创建bean 代理对象
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean(String, RootBeanDefinition ,Object[] )
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance(String, RootBeanDefinition, Object[])
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(String, RootBeanDefinition, BeanWrapper)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization(Object, String)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization(@Nullable, String)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary(Object bean, String beanName, Object cacheKey)
-
检查是否是 AOP 相关的配置或工具类。
-
检查是否 满足AOP代理条件。
-
获取满足条件的通知(advice)。 目标类中,只要有一个方法满足 切入点(Pointcut)条件,就将通知(advice)添加到代理类拦截器中。
-
创建AOP代理实例。
/**
* 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;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have 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;
}
View Code
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy(Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource)
org.springframework.aop.framework.ProxyProcessorSupport#evaluateProxyInterfaces(Class, ProxyFactory)
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#buildAdvisors(String beanName, Object[] specificInterceptors)
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
-
遍历目标类所有接口。
-
处理满足条件的通知和公共通知。
-
通过代理工厂类,创建代理类。
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
protected Object createProxy(Class beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
return proxyFactory.getProxy(classLoader);
}
View Code
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy(Class beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource)
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy()
org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy()
org.springframework.aop.framework.AopProxy#getProxy(java.lang.ClassLoader)
- 创建 AopProxy 代理实例。这里区分 JDK动态代理(JdkDynamicAopProxy) 和 Cglib 代理(ObjenesisCglibAopProxy)。
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(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);
}
View Code
- 使用 AopProxy 代理创建最终的代理类。区别两种代理情况。
AopProxy 创建代理类实例:
JDK 生成动态代理简单,直接调用JDK的方法生成。org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
View Code
JdkDynamic 生成的代理类:
package com.sun.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import org.springframework.context.support.learning.aop.User;
public final class $Proxy35 extends Proxy implements User {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy35(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String doTask() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("org.springframework.context.support.learning.aop.User").getMethod("doTask");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
View Code
Cglib生成代理类,使用ASM字节码,稍微复杂些。 org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)
@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");
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));
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);
}
}
View Code
Cglib 生成的代理类太复杂,这里就不展示。
四. 通过代理类实例调用业务方法和增强通知(Advice)
JdkDynamic代理:
org.springframework.aop.framework.JdkDynamicAopProxy#invoke(Object proxy, Method method, Object[] args)
-
获得当前方法的 所有通知(Advice) /拦截器。获取后,缓存中放一份。
-
如果没找到满足条件的通知(Advice),则直接调用实际方法。AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse)
-
通过目标方法,方法参数,通知(Advice) 创建调用方法的 ReflectiveMethodInvocation 实例。
-
调用 ReflectiveMethodInvocation#proceed()。 这个方法会轮询调用 通知(Advice) ,并最终调用实际的方法。
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
@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();
}
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);
}
}
View Code
(代理类实例)user.doTask() -> JdkDynamicAopProxy#invoke()
-> ReflectiveMethodInvocation#proceed() -> ExposeInvocationInterceptor#invoke(MethodInvocation mi)
AspectJAroundAdvice#invoke(MethodInvocation mi)
MethodBeforeAdviceInterceptor#invoke(MethodInvocation mi)
AspectJAfterAdvice#invoke(MethodInvocation mi)
AfterReturningAdviceInterceptor#invoke(MethodInvocation mi)
AspectJAfterThrowingAdvice#invoke(MethodInvocation mi)
AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments)
Cglib代理:
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept
-
获得当前方法的 所有通知(Advice) /拦截器。缓存中放一份。
-
如果没找到满足条件的通知(Advice),则直接调用代理方法。org.springframework.cglib.proxy.MethodProxy#invoke(Object obj, Object[] args)
-
通过目标方法,方法参数,通知(Advice) 创建调用方法的 CglibMethodInvocation 实例。 CglibMethodInvocation 是 ReflectiveMethodInvocation 子类。
-
调用 CglibMethodInvocation#proceed()。 这个方法会轮询调用 通知(Advice) ,并最终调用实际的方法。这个和JdkDynamic 类似 。
Original: https://www.cnblogs.com/StreamPlume/p/16023150.html
Author: 流羽
Title: Spring 5 源码解析- AOP原理分析-5
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/574106/
转载文章受原作者版权保护。转载请注明原作者出处!