Spring AOP 源码分析

【阅读前提】: 需了解AOP注解开发流程:链接

一、注解 @EnableAspectJAutoProxy

在配置类中添加注解@EnableAspectJAutoProxy,便开启了AOP(面向切面编程) 功能。此注解也是了解AOP源码的入口。

@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {

【1】@EnableAspectJAutoProxy是什么?我们进入注解,查看其源码如下:发现调用EnableAspectJAutoProxy类,同时使用 @Import注解向容器中导入 AspectJAutoProxyRegistrar 组件:作用是给容器中注册自定义的Bean

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

【2】进入AspectJAutoProxyRegistrar类,调用registerBeanDefinitions中的register...Necessary方法注册组件。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//向容器(registry)中注入组件	AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

【3】 进入register...Necessary方法,通过源码分析:该方法向容器中注册一个AnnotationAwareAspectJAutoProxyCreator(支持注解模式的面向切面自动代理创建器)组件,其名称为internalAutoProxyCreator。需要注意的是其注册的是一个BeanDefinitionBean的定义信息,并没有实例化。后续分析时会说到) 。

//debug 进来后,发现cls参数的值等于 AnnotationAwareAspectJAutoProxyCreator 这个参数也是直接写死的,如下:。
//registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");//AUTO_PROXY_CREATOR_BEAN_NAME == internalAutoProxyCreator //因第一次进来,所以容器中不存在 internalAutoProxyCreator if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}//创建一个新的对象封装 clsRootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);//将封装的cls对象注册到容器中,并将名称定义为AUTO_PROXY_CREATOR_BEAN_NAME == internalAutoProxyCreator 就上上述判断的语句。//此时我们就应该分析 AnnotationAwareAspectJAutoProxyCreator对象的作用registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;
}

二、研究AnnotationAwareAspectJAutoProxyCreator

此自动代理创建器的内部功能,其等价于AOP的主要功能。 此类的继承结构如下:

我们进入自动代理的抽象父类AbstractAutoProxyCreator中发现,其实现了SmartInstantiationAwareBeanPostProcessor后置处理器(在bean初始化前后做一些操作,AOP的特点)和BeanFactoryAware自动装配BeanFactory

@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupportimplements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

AOP原理分析技巧:【看给容器中注册了什么组件, 这个组件什么时候工作,这个组件的功能是什么?】,研究透这些,原理也就清楚了。

我们从AbstractAutoProxyCreator父类向AnnotationAwareAspectJAutoProxyCreator子类的顺序,查看其内部关于后置处理器和自动装备的方法并加入断点:

【1】AbstractAutoProxyCreator:包含后置处理器前后的两个方法和自动装配的方法。

//后置处理器相关的方法1
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {Object cacheKey = getCacheKey(beanClass, beanName);if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {if (this.advisedBeans.containsKey(cacheKey)) {return null;}if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return null;}}//后置处理器相关的方法2
@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;
}//自动装备相关的方法
@Override
public void setBeanFactory(BeanFactory beanFactory) {this.beanFactory = beanFactory;
}

【2】AbstractAdvisorAutoProxyCreator:重写了setBeanFactory方法。

//自动装备方法
@Override
public void setBeanFactory(BeanFactory beanFactory) {super.setBeanFactory(beanFactory);if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);}initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}

【3】对 2中的initBeanFactory方法进行了重写。

@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.initBeanFactory(beanFactory);if (this.aspectJAdvisorFactory == null) {this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);}this.aspectJAdvisorsBuilder =new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}

三、Debug 测试类流程梳理

【1】创建 IOC 容器,传入主配置类MainConfigOfAOP

//获取容器中的类
ApplicationContext ApplicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);

【2】调用AnnotationConfigApplicationContext构造器:注册配置类和刷新容器(创建容器中的所有Bean,类似于初始化容器)

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {//创建对象this();//注册配置类register(annotatedClasses);//刷新容器refresh();
}

【3】调用refresh方法:主要查看registerBeanPostProcessors(beanFactory); 方法,其作用是注册bean后置处理器,用方便来拦截bean的创建。

@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {....// 注册 bean 后置处理器,用来拦截 bean 的创建registerBeanPostProcessors(beanFactory);....
}

【4】进入registerBeanPostProcessors调用的方法:先获取 IOC 容器中已经定义了的需要创建对象的所有后置处理器BeanPostProcessor(已定义:指我们在解析配置类的时候@EnableAspectJAutoProxy会为我们注册一个AnnotationAwareAspectJAutoProxyCreator后置处理器的定义,包括默认的一些后置处理器的定义)例如:

上述列表中的internalAutoProxyCreator后置处理器,就是我们分析@EnableAspectJAutoProxy时注入的那个处理器。后置处理的注册分为以下三种情况:
 ■ 优先注册实现了PriorityOrdered(优先级)接口的BeanPostProcessors
 ■ 其次注册实现了Ordered接口的BeanPostProcessors
 ■ 注册所有常规Beanpstprocessors
internalAutoProxyCreator后置处理器实现了Ordered接口。分析代码可知:【根据bean定义名称internalAutoProxyCreatorbeanFactory中获取注入的后置处理器】调用的方法 = beanFactory.getBean(ppName, BeanPostProcessor.class);

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {//获取ioc容器中已经定义了的需要创建对象的所有 BeanPostProcessorString[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);//也会注意一些其他后置处理器,bean 是在 beanPostProcessor 实例化期间创建的,即 bean 不适合由所有 beanPostProcessors 处理。这个其实不重要,可以省略...int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 +    postProcessorNames.length;beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));//判断哪些后置处理器配置了优先级for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}// 优先注册实现了 PriorityOrdered(优先级) 的 BeanPostProcessorssortPostProcessors(priorityOrderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// 其次注册实现了Ordered 接口的 BeanPostProcessors.List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();for (String ppName : orderedPostProcessorNames) {//根据 bean定义的名称internalAutoProxyCreator 从 beanFactory 中获取注入的后置处理器BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);orderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}sortPostProcessors(orderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, orderedPostProcessors);// 注册所有常规beanpstprocessors。List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();for (String ppName : nonOrderedPostProcessorNames) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);nonOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);// 最后,重新注册所有内部beanpstprocessors。sortPostProcessors(internalPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, internalPostProcessors);

【5】进入上述所说的beanFactory.getBean(ppName, BeanPostProcessor.class); 方法如下:因第一次进入容器,因此获取不到实例。会通过 getSingleton方法创建BeanPostProcessor的实例,并保存到容器中。

@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {return doGetBean(name, requiredType, null, false);
}//上述方法内部调用的是 doGetBean(name, requiredType, null, false); 代码如下:
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {//因为第一次获取,容器中不存在此实例。因此 sharedInstance==nullObject sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {...}else {// 创建 bean 实例if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}}

【6】创建internalAutoProxyCreatorAnnotationAwareAspectJAutoProxyCreator实例。步骤如下:

//1、创建bean的实例
createBean(beanName, mbd, args);
//2、给Bean 的各属性赋值
populateBean(beanName, mbd, instanceWrapper);
//3、初始化 bean ,比较重要,因为后置处理器就是在此前后进行工作的
exposedObject = initializeBean(beanName, exposedObject, mbd);

【7】重点是:初始化initializeBean方法,查看实现的步骤如下:

//1、调用 invokeAwareMethods 处理Aware 接口的方法回调,beanName=internalAutoProxyCreator 实现了 BeanAware 接口
invokeAwareMethods(beanName, bean);
//2、应用后置处理器 BeforeInitialization
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//3、执行自定义的初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
//4、执行后置处理器的 After方法
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//下面是上述方法的具体实现//1、invokeAwareMethods 实现如下:
private void invokeAwareMethods(final String beanName, final Object bean) {if (bean instanceof Aware) {//.....//实现了 BeanFactoryAware 接口,因此执行 setBeanFactory.//bean==AnnotationAwareAspectJAutoProxyCreatorif (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}
}//2、applyBeanPostProcessorsBeforeInitialization 实现如下:
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//获取所有的后置处理器,执行前置Before 处理器。for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessBeforeInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;
}//3、invokeInitMethods 方法的具体实现
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {boolean isInitializingBean = (bean instanceof InitializingBean);if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {if (logger.isTraceEnabled()) {logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");}if (System.getSecurityManager() != null) {try {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((InitializingBean) bean).afterPropertiesSet();return null;}, getAccessControlContext());}catch (PrivilegedActionException pae) {throw pae.getException();}}else {((InitializingBean) bean).afterPropertiesSet();}}if (mbd != null && bean.getClass() != NullBean.class) {String initMethodName = mbd.getInitMethodName();if (StringUtils.hasLength(initMethodName) &&!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&!mbd.isExternallyManagedInitMethod(initMethodName)) {invokeCustomInitMethod(beanName, bean, mbd);}}
}//4、applyBeanPostProcessorsAfterInitialization 具体实现
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;
}

【8】执行Aware初始化时,会调用setBeanFactory方法,我们追下去会发现调用的是AbstractAdvisorAutoProxyCreatorsetBeanFactory方法(就是我们分析AnnotationAwareAspectJAutoProxyCreator继承关系时的父类 )。

AnnotationAwareAspectJAutoProxyCreator(AbstractAdvisorAutoProxyCreator).setBeanFactory(BeanFactory)line:58
@Override
public void setBeanFactory(BeanFactory beanFactory) {//调用父类的 setBeanFactorysuper.setBeanFactory(beanFactory);if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);}//AnnotationAwareAspectJAutoProxyCreator  方法对此进行了重写initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}

【9】进入initBeanFactory方法,我们知道此方法已被AnnotationAwareAspectJAutoProxyCreator重写:

//位于 AnnotationAwareAspectJAutoProxyCreator 类中
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.initBeanFactory(beanFactory);if (this.aspectJAdvisorFactory == null) {//创建了放射的通知工厂this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);}this.aspectJAdvisorsBuilder =new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}

【10】最终BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功,将其添加到beanFactory中。

for (String ppName : orderedPostProcessorNames) {//实例 pp==AnnotationAwareAspectJAutoProxyCreator BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);//放入 ordered后置处理器集合orderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}
}
//将处理器按优先级排序
sortPostProcessors(orderedPostProcessors, beanFactory);
//调用注册方法
registerBeanPostProcessors(beanFactory, orderedPostProcessors);//上述注册方法的内部代码
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {//将后置处理器都添加到bean工厂for (BeanPostProcessor postProcessor : postProcessors) {beanFactory.addBeanPostProcessor(postProcessor);}
}

四、后置处理器创建后的操作

【1】以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程。接下来就是对创建后的流程进行说明:AnnotationAwareAspectJAutoProxyCreator是继承InstantiationAwareBeanPostProcessor的后置处理器:我们在上面说的IOC容器初始化时,会调用 refresh方法:我们进入此方法看下,我们之前分析registerBeanPostProcessors方法,接下来分析finishBeanFactoryInitialization方法(实例所有剩余的单实例bean)完成BeanFactory初始化工作。

@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//......// 注册 bean后置处理器 来拦截 bean 的创建。registerBeanPostProcessors(beanFactory);//......// 初始化特定上下文子类中的其他特殊bean。onRefresh();//......// 实例化所有剩余的(非延迟初始化)单例。finishBeanFactoryInitialization(beanFactory);
}

【2】遍历获取容器中所有的Bean,依次创建对象 getBean(beanName); 流程:getBean->doGetBean()->getSingleton()getBean方法如下:先从缓存中获取当前bean,如果能获取到说明bean是之前被创建过的,直接使用,否则创建bean;只要是创建好的bean都会被缓存起来。

// 先检查单例缓存中是否有已存在手动注册的单例,如果存在说明之前bean已创建
Object sharedInstance = getSingleton(beanName);
//缓存中不存在 bean 时才创建该单例 bean
if (sharedInstance != null && args == null) {//...
}else{//创建bean实例。if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}
}

【2.1】进入创建bean的步骤:createBean方法,首先会调用resolveBeforeInstantiation方法,让beanPostProcessors后置处理器有机会返回代理对象而不是目标bean实例。如果能返回则直接使用,如果不能则调用doCreateBean方法来创建实例。

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {/*现获取类的基本信息 例如:Root bean: class [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]; scope=singleton等等*/RootBeanDefinition mbdToUse = mbd;//......//让beanPostProcessors有机会返回代理而不是目标bean实例。		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}//通过此方法,先调用 aware、前置处理器、bean初始化、后置处理器 ,之前有分析过。Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}

BeanPostProcessor是在Bean对象创建完成初始化前后调用的】
InstantiationAwareBeanPostProcessor是在创建bean实例之前先尝试用后置处理器返回代理对象】
 后置处理器与后置处理器不同,具体什么时候调用,需要根据不同情况而定。

【2.1.1】分析resolveBeforeInstantiation方法(让beanPostProcessors有机会返回代理对象):我们分析的AnnotationAwareAspectJAutoProxyCreator就是InstantiationAwareBeanPostProcessor类型的后置处理器。会在任何bean创建之前先尝试返回bean的代理实例。

@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}
}//上面两个方法的源码展示
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {//获取所有的后置处理器for (BeanPostProcessor bp : getBeanPostProcessors()) {//如果后置处理器是 InstantiationAwareBeanPostProcessor 类型的处理器则执行 postProcessBeforeInstantiation 方法。//我们分析的 AnnotationAwareAspectJAutoProxyCreator 就是 InstantiationAwareBeanPostProcessor 类型的处理器if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;//***** 后续分析Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);if (result != null) {return result;}}}return null;
}

【2.1.1.1】接着分析上述的postProcessBeforeInstantiation方法:内容较多,放在五中分析。

【2.1.2】分析doCreateBean方法,之前有介绍过,我们在看下源码:就是对创建的目标类前后对后置处理器的方法进行初始化。才是真正创建一个bean的实例。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {//创建 bean 实例instanceWrapper = createBeanInstance(beanName, mbd, args);//bean 属性赋值populateBean(beanName, mbd, instanceWrapper);//初始化 beanexposedObject = initializeBean(beanName, exposedObject, mbd);
}//初始化方法 initializeBean 的源码
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {//初始化 aware 接口的类invokeAwareMethods(beanName, bean);//后置处理器 Before 方法初始化wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//初始化类invokeInitMethods(beanName, wrappedBean, mbd);//后置处理器 after 方法初始化wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//返回创建好的类return wrappedBean;
}

五、postProcessBeforeInstantiation方法分析

【1】每个bean创建之前,调用此方法。我们主要观察业务逻辑MathCalculator类和切面LogAspects类的创建。

//当bean = MathCalculator or LogAspects 我们着重分析此方法,其他的略过
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {Object cacheKey = getCacheKey(beanClass, beanName);if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {//判断当前 bean 是否在 advisedBeans 中(保存了所有需要增加的 bean:意思就是添加了切面的内容),第一次进行肯定是不包含的所以会跳过if (this.advisedBeans.containsKey(cacheKey)) {return null;}//isInfrastructureClass 判断当前类是否为基础类型的,也就是实现了 Advice、Pointcut、Advisor、AopInfrastructureBean //或者是否为切面注解标注的类 (@Aspect),第一个 MathCalculator = false//shouldSkip 是否需要跳过:内部是获取候选的增强器(也就是切面内的通知方法)//将所有的增强器封装成了 List<Advisor> 集合,增强器的类型是 InstantiationModelAwarePointcutAdvisorif (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return null;}}// targetSource = nullTargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {if (StringUtils.hasLength(beanName)) {this.targetSourcedBeans.add(beanName);}Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}//直接返回空,进入我们配置类中,创建 MathCalculator 对象return null;
}

【2】上述代码中的shouldSkip源码:

@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {//获取所有的增强器 考虑通过缓存方面名称列表进行优化List<Advisor> candidateAdvisors = findCandidateAdvisors();for (Advisor advisor : candidateAdvisors) {//我们的增强器都是 InstantiationModelAwarePointcutAdvisor 类型的,不是AspectJPointcutAdvisor 所以跳过if (advisor instanceof AspectJPointcutAdvisor &&((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {return true;}}//父类直接返回 falsereturn super.shouldSkip(beanClass, beanName);
}

【3】创建完MathCalculator后,调用postProcessAfterInitialization

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {// cacheKey = calculatorObject cacheKey = getCacheKey(bean.getClass(), beanName);//判断之前是否代理过if (this.earlyProxyReferences.remove(cacheKey) != bean) {//包装目标类,如果需要的话return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;
}

【3.1】查看包装方法wrapIfNecessary的源码:分析后得出如下结论:以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {//...... 省略的都是判断是否为切面类或以代理类//如果需要就创建代理类//getAdvicesAndAdvisorsForBean 获取能在当前类使用的增强器Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {//保存当前 bean 在advisedBeans 表示当前bean 被处理了this.advisedBeans.put(cacheKey, Boolean.TRUE);//创建代理对象 ****重点,返回的是一个通过 Cglib 代理的对象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;

【3.1.1】进入当前类使用的增强器方法:getAdvicesAndAdvisorsForBean

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {//获取可用的增强器List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();
}

【3.1.1.1】进入获取可用增强器的方法:findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {//获取后置增强器List<Advisor> candidateAdvisors = findCandidateAdvisors();//找到能在当前bean中使用的增强器(找那些方法能够切入到当前方法的)List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {//对增强器进行了排序eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;
}//上面获取当前bean中使用的增强器的方法源码
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try {//通过 AopUtils工具类获取所有的通知方法return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);}finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}
}//工具类方法源码展示
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List<Advisor> eligibleAdvisors = new ArrayList<>();for (Advisor candidate : candidateAdvisors) {//我们的增强器不是此类型if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {// already processedcontinue;}//判断增强器是否可用,我们的都是可用的if (canApply(candidate, clazz, hasIntroductions)) {//将所有可以使用的增强器,加入到可用的增强器集合中eligibleAdvisors.add(candidate);}}return eligibleAdvisors;
}//判断是否为可用的增强器的方法 canApply源码:
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;}
}

【3.1.2】进入代理对象的创建方法:createProxy

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);}//使用代理工厂创建对象return proxyFactory.getProxy(getProxyClassLoader());
}

【3.1.2.1】进入代理工厂创建对象的方法proxyFactory.getProxy的源码:

public Object getProxy(@Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);
}//进入 createAopProxy().getProxy 内部的内部方法
@Override
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.");}//创建 JDK 代理或者 Cglib 代理。如果实现了接口则使用 JDK 代理,否则Cglib 代理if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}
}

六、目标方法执行

【1】容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如:增强器,目标对象…)

【2】CglibAopProxy.intercept(); 拦截目标方法执行如下:主要是根据ProxyFactory对象获取将要执行的目标方法的拦截器链。
 1)、如果没有拦截器链,直接执行目标方法。
 2)、如果有拦截器链,吧需要执行的目标对象,目标方法,拦截器链等信息传入创建一个CglibMethodInvocation对象,并调用retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); 方法。

@Override
@Nullable
public 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) {oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);//根据 ProxyFactory 对象获取将要执行的目标方法的拦截器链List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;//如果没有拦截器链,直接执行目标方法。if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = methodProxy.invoke(target, argsToUse);}//如果有拦截器链,吧需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation 对象,并调用如下方法。else {retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {//......}
}

【3】 拦截器链:List<Object> chain = advised.getInterceptorsAndDynamicInterceptionAdvice的源码展示:
 1)、List<Object> interceptorList中保存了所有拦截器,总计5个。一个默认的ExposeInvocationInterceptor和 4个增强器。
 2)、遍历所有的增强器,将其转为Interceptor(拦截器):registry.getInterceptors(advisor);

@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {//......//获取所有的增强器进行遍历for (Advisor advisor : advisors) {//判断是否为切面的增强器if (advisor instanceof PointcutAdvisor) {//......//将增强器转化为 MethodInterceptorMethodInterceptor[] interceptors = registry.getInterceptors(advisor);if (mm.isRuntime()) {for (MethodInterceptor interceptor : interceptors) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {interceptorList.addAll(Arrays.asList(interceptors));}}else if (advisor instanceof IntroductionAdvisor) {IntroductionAdvisor ia = (IntroductionAdvisor) advisor;if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {Interceptor[] interceptors = registry.getInterceptors(advisor);interceptorList.addAll(Arrays.asList(interceptors));}}else {Interceptor[] interceptors = registry.getInterceptors(advisor);interceptorList.addAll(Arrays.asList(interceptors));}}return interceptorList;
}

 3)、将增强器转为MethodInterceptor,转化方式如下:最终返回拦截器链(每一个通知方法又被包装为方法拦截器,后期都是利用MethodInterceptor机制)。

@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {List<MethodInterceptor> interceptors = new ArrayList<>(3);Advice advice = advisor.getAdvice();//如果是 MethodInterceptor 直接加入到 list 中if (advice instanceof MethodInterceptor) {interceptors.add((MethodInterceptor) advice);}//如果不是则,使用 AdvisorAdapter 将增强器转为 MethodInterceptorfor (AdvisorAdapter adapter : this.adapters) {if (adapter.supportsAdvice(advice)) {interceptors.add(adapter.getInterceptor(advisor));}}if (interceptors.isEmpty()) {throw new UnknownAdviceTypeException(advisor.getAdvice());}return interceptors.toArray(new MethodInterceptor[0]);
}

【4】拦截器链有了之后,创建CglibMethodInvocation并执行proceed方法:

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

七、拦截器链的触发过程

【1】拦截器链展示:除了默认的方法ExposeInvocationInterceptor剩下的 4个都是我们切面中的方法。

【2】如果没有拦截器执行目标方法执行代理对象CglibMethodInvocationproceed方法:

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

【3】进入proceed方法:

@Override
@Nullable
public Object proceed() throws Throwable {//判断连接器栏的长度是否 == 0,此方法会在拦截器链的最后一个链时调用if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {//执行目标方式,输入为:MathCalculator...div...return invokeJoinpoint();}//获取下标=0的拦截器 ExposeInvocationInterceptorObject interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {//下标0 跳过......}else {// this=ReflectiveMethodInvocationreturn ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}
}

【4】进入[MethodInterceptor] interceptorOrInterceptionAdvice).invoke(this); 方法:会循环调用list中的拦截器,直到后置处理器:AspectJMethodBeforeAdvice

//ThreadLocal 线程共享数据 (共享 MethodInvocation)
private static final ThreadLocal<MethodInvocation> invocation =new NamedThreadLocal<>("Current AOP method invocation");@Override
public Object invoke(MethodInvocation mi) throws Throwable {//获取 invocation MethodInvocation oldInvocation = invocation.get();//将当前方法,放入 invocationinvocation.set(mi);try {//执行 cglib 的proceed() 就获取到了下标为1的拦截器 AspectJAfterThrowingAdvicereturn mi.proceed();}finally {//执行后置通知invocation.set(oldInvocation);}
}

【5】 当advice=AspectJMethodBeforeAdvice后置处理器时,invoke方法如下:

@Override
public Object invoke(MethodInvocation mi) throws Throwable {//执行后置处理器的 before 方法//输出如下:div运行。。。@Before:参数列表是:{[2, 3]}this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());//进入上述展示的 processd 方法,此时进入第一个判断语句,执行目标方法return mi.proceed();
}

【6】 后置处理器的After方法执行的invoke方法展示:最终执行结果的返回方法。

@Override
public Object invoke(MethodInvocation mi) throws Throwable {try {return mi.proceed();}finally {//执行 after 方法:div结束。。。@AfterinvokeAdviceMethod(getJoinPointMatch(), null, null);}
}

【7】上述分析的流程图如下:根据链表循环向下执行,当最后一个后置处理器的before执行完成后,进行目标方法,并进行回流执行拦截器的目标方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/626878.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

编码技巧:如何在Golang中高效解析和生成XML

编码技巧&#xff1a;如何在Golang中高效解析和生成XML 引言Golang中的XML基础解析XML文件生成XML文件错误处理和调试高级技巧和最佳实践总结 引言 在当今数据驱动的编程世界中&#xff0c;有效地处理各种数据格式是每个开发人员必备的技能之一。其中&#xff0c;XML&#xff…

【人工智能:现代方法】第19章:样例学习

智能体学习&#xff08;learning&#xff09;&#xff1a;一个智能体通过对世界进行观测来提高它的性能机器学习&#xff08;machine learning&#xff09;&#xff1a;智能体是一台计算机 —— 一台计算机观测到一些数据&#xff0c;基于这些数据构建一个模型&#xff08;mode…

并发编程之三大特性及JMM内存模型

目录 原子性 如何保证原子性 可见性 如何保证可见性 有序性 如何保证有序性 Java内存模型(JMM内存模型) Java内存模型的一些关键概念&#xff1a; 主内存与工作内存交互协议 Java内存模型通过以下手段来确保多线程程序的正确性&#xff1a; 锁机制 volatile volat…

1-数组-有效的数独

这是数组的第一题&#xff0c;从现在开始开启数组篇章。力扣链接。 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的…

Fpga开发笔记(二):高云FPGA发开发软件Gowin和高云fpga基本开发过程

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/135620590 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

【Redis配置】Linux下的Redis安装配置

压缩包方式的Redis下载与安装 进入官网 Redis官网&#xff1a;https://redis.io/download/ 往下翻可以找到其他版本的Redis&#xff0c;或者访问https://download.redis.io/releases/查找自己所需Redis版本。 下载自己所需版本 此处我选择下载的是6.2.14版本 上传到Linux…

墙地砖外形检测的技术方案-图像分割

基础原理 由于对碗口进行缺口检测&#xff0c;因此只需要碗口的边界信息。得到陶瓷碗区域填充后的图像&#xff0c;对图像进行边缘检测。这是属于图像分割中的内容&#xff0c;在图像的边缘中&#xff0c;可以利用导数算子对数字图像求差分&#xff0c;将边缘提取出来。 案例…

Vue:将以往的JQ页面,重构成Vue组件页面(组件化编码大致流程)

一、实现静态组件 组件要按照功能点拆分&#xff0c;命名不要与HTML元素冲突。 1、根据UI提供的原型图&#xff0c;进行结构设计&#xff0c;结构设计的粒度以是否方便给组件起名字为依据。并梳理好对应组件的层级依赖关系。 2、设计好结构后&#xff0c;开始写对应的组件&am…

pl/sql程序块的使用

-- Created on 2024-01-15 by ADMINISTRATOR declare -- Local variables hererecord_tablename varchar2(100);---test_record表名record_StartNo integer(19);---test_record开始编号temp_No integer(19);maxnbbh integer(19);nCnt integer : 20;fi…

家用小型洗衣机哪款性价比高?好用的内衣洗衣机推荐

现在大多数的上班族&#xff0c;面临的都是早九晚六的工作&#xff0c;而且工作完下班回家还是面对各种各样的家务&#xff0c;特别是清洗需要换洗的洗衣&#xff0c;属实是有点辛苦了。可能很多人为了方便&#xff0c;每次洗衣服的都是把一堆衣服直接丢进洗衣机&#xff0c;直…

EVE-NG的环境导入IOL组件

IOL或IOS On Linux&#xff0c;也称为IOU或IOS On Unix。IOL是一个模拟器&#xff0c;一般仅思科使用。IOL指为i386架构编译的Linux版本。IOU指为Sparc架构编译的Unix&#xff08;Solaris&#xff09;版本。由于IOL是内部IOS版本&#xff0c;因此IOL只能由Cisco授权客户使用。需…

UniApp+Vue智慧工地信息化管理云平台源码(支持多工地使用)

智慧工地建设的意义 1、提高工程效率 智慧工地可以通过数字化手段&#xff0c;将工地的各个方面进行数字化存储和管理&#xff0c;从而实现的实时监测和共享。这可以大大提高工程的效率&#xff0c;减少工程中的人工干预&#xff0c;并且可以为后续的工程维护和升级提供便利。…

c++中的以及链表的基础使用

c中的& 通俗的立减即为对一个变量起别名。&#xff08;是和指针有区别的&#xff09; 以下为两个示例程序&#xff1a; 通过&代替了以往对地址的传递。从而实现了对a和b的交换。 p为a的别名&#xff0c;对p操作即为对a操作。故最后输出a的值为10. 链表的基础应用 链…

Windows11搭建Python环境(2)- Anaconda虚拟环境中安装Git

在搭建MetaGPT运行环境过程中&#xff0c;使用了Anaconda虚拟环境&#xff0c;在运行MetaGPT时出现错误&#xff1a; 可以看到是没有找到git指令。 在Windows上安装Git&#xff0c;可以直接去官网下载.exe文件&#xff0c;然后安装即可。 但是上面安装完成后&#xff0c;是无…

三方接口对接常见数据处理方式汇总

文章目录 数据请求格式application/json接收发送 multipart/form-data接收发送 application/x-www-form-urlencoded接收发送 text/xml接收发送 Request请求中各个数据载体获取方法HeaderParameterInputStreamAttribute 二次封装HttpServletRequest参考 验签与加密 日常开发中&a…

【Python_PySide6学习笔记(三十一)】基于PySide6实现自定义串口设备连接界面类:可实现串口连接断开、定时发送等功能

基于PySide6实现自定义串口设备连接界面类:可实现串口连接关闭、定时发送等功能 基于PySide6实现自定义串口设备连接界面类:可实现串口连接关闭、定时发送等功能前言一、界面布局二、串口相关功能实现三、完整代码四、调用方法五、实现效果基于PySide6实现自定义串口设备连接…

快慢指针-Floyd判圈算法

对于环形链表是否存在环的做法&#xff0c;普通算法可以通过额外Hash数组来存储链表元素&#xff0c;直到Hash数组中出现重复元素。时间复杂度O(n)&#xff0c;空间复杂度O(n) Floyd判圈算法通过利用快慢指针的移动来实现&#xff0c;时间复杂度O&#xff08;n&#xff09;&am…

【备战蓝桥杯】今天给大家整点解压的~

【备战蓝桥杯】今天给大家整点解压的~ 蓝桥杯备赛 | 洛谷做题打卡day8 文章目录 【备战蓝桥杯】今天给大家整点解压的~ 蓝桥杯备赛 | 洛谷做题打卡day8[NOIP2017 普及组] 成绩题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提…

【C语言编程之旅 1】刷题篇-初识c语言

文章目录 第一题答案及解析 第二题答案及解析 第三题答案及解析 第四题答案及解析 第五题答案及解析 第六题答案及解析 第一题 答案及解析 C语言中内置类型包括&#xff1a; char //字符数据类型 short //短整型 int //整形 long //长整型 long long //更长的整形 float //单精…

ArcGIS Pro 拓扑编辑和常见一些拓扑错误处理

7.4 拓扑编辑 拓扑编辑也叫共享编辑&#xff0c;多个数据修改时&#xff0c;一块修改&#xff0c;如使用数据&#xff1a;chp7\拓扑检查.gdb,数据集DS下JZX、JZD和DK&#xff0c;加载地图框中&#xff0c;在“地图”选项卡下选择“地图拓扑”或“ds_Topology(地理数据库)”&…