Spring AOP 源码执行流程
Spring AOP 源码执行流程
建议阅读AOP文章顺序:
JDK代理和CGLIB代理之间的区别:
原生JDK代理:
- 原生JDK代理是Java提供的一种动态代理方式,通过
java.lang.reflect.Proxy
类和接口实现;- JDK代理只能代理具体的类,即:实现接口的具体的类;
- JDK代理在运行时通过反射机制动态生成代理类,代理类实现了被代理接口,并将方法调用委托给InvocationHandler处理器;
- JDK代理要求被代理的类必须实现接口。
CGLIB代理:
- CGLIB(Code Generation Library)是一个强大的第三方类库,可以在运行时生成字节码,创建代理对象。
- CGLIB代理可以代理普通的类,不仅仅限于接口。
- CGLIB代理通过继承的方式创建代理类,代理类继承了被代理类,并重写了被代理方法。
- CGLIB代理不要求被代理的类实现接口。
在选择使用原生JDK代理还是CGLIB代理时,可以考虑以下因素:
- 如果被代理的类是接口类型,并且不需要继承其他类,则可以选择原生JDK代理。
- 如果被代理的类不是接口类型,或者需要继承其他类,则可以选择CGLIB代理。
- 需要注意的是,CGLIB代理在生成代理类时会涉及到字节码操作,相比原生JDK代理会更加复杂和消耗更多的资源。因此,在性能要求较高的情况下,可以优先考虑原生JDK代理。
一、执行步骤
大致可以分为几步:(注解方式和配置文件方式)
- 1、注册可以处理Spring AOP 注解方式的类到Spring IOC中;(配置文件spring.xml方式和注解方式的区别:就是往Spring IOC中注册解析AOP xml标签的过程)
- 注解方式注册:
AnnotationAwareAspectJAutoProxyCreator
类 - 配置文件方式注册:
AspectJAutoProxyBeanDefinitionParser
类 这个只是解析xml配置文件节点,最后也是注册AnnotationAwareAspectJAutoProxyCreator
这个。
- 注解方式注册:
- 2、构建 拦截器链(或者叫通知链),创建代理;并注册到beanFacatroy中。
- 3、执行目标方法时,转为执行代理(就是当调用我们要增强的某个方法时,转而按切面配置的通知增强方式进行执行)。
- 4、通知链的执行。
二、注册
2.1 基于注解方式注册
// 方式一:
@Configuration
@ComponentScan(basePackages = "aop")
@EnableAspectJAutoProxy(proxyTargetClass = true) // 注解方式启动AOP
public class AspectConfig {
}
// 方式二:
在不使用@EnableAspectJAutoProxy的时候, 在spring.xml中配置 <aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="false"/>
我们可以点击一下aspectj-autoproxy,可以进入到 spring-aop.xsd中,查看该节点的source 用的也是 AnnotationAwareAspectJAutoProxyCreator
// 注意:这两种方式,切面都是基于@AspectJ注解定义的。
通过 @EnableAspectJAutoProxy
这个注解我们可以找到在Spring 中只有一处是对该注解的处理:(该类是在 spring-context
工程的org.springframework.context.annotation包中);这里就是入口了。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* @param importingClassMetadata AspectJ切面的配置类,如:a-spring-test-pro 项目中的aop.aspect.AspectConfig切面配置
* @param registry 当前的 BeanDefinitionRegistry,将配置的 AspectJ注册到 registry
* 入口:
* 根据 @EnableAspectJAutoProxy的属性去注册,升级,配置AspectJ的自动代理对象创建者
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
// 1. 注册默认的 AnnotationAwareAspectJAutoProxyCreator 到 当前的registry中
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 2. 获取注解上的属性信息;这里获取的 @EnableAspectJAutoProxy上的
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
// 3. 设置标签
if (enableAspectJAutoProxy != null) {
// 3.1 获取并处理proxy-target-class属性:
// false表示使用java原生动态代理;
// true表示使用CGLib动态.
// 但是对于一些没有接口实现的类来说,即使设置为false也会使用CGlib进行代理.
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 3.2 获取并处理expose-proxy标签,实现对于内部方法调用的AOP增强
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
先跟(1.)注册默认的 AnnotationAwareAspectJAutoProxyCreator 到 当前的registry中;一定要理解这句话,查看上面方法的参数试着理解。
//1. 注册默认的 AnnotationAwareAspectJAutoProxyCreator 到 当前的registry中 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
就做一个件事,看看
register
有没有注册AnnotationAwareAspectJAutoProxyCreator.class,如果有返回了null
,如果没有就new一个,注册。主要就是进入到·
AopConfigUtils#registerOrEscalateApcAsRequired()
这个核心方法
public abstract class AopConfigUtils {
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static {
// Set up the escalation list...
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
// -> 来到这里
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
// --> 进入这个
/**
* 注册默认的 AnnotationAwareAspectJAutoProxyCreator 到 当前的registry中
* @param registry 当前的BeanDefinitionRegistry
* @param source
* @return
*/
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
// ---> 核心处理方法
/**
* 将 AnnotationAwareAspectJAutoProxyCreator(代理创建器(ProxyCreator))注册到当前的 registry中
* @param cls AnnotationAwareAspectJAutoProxyCreator
* @param registry BeanDefinitionRegistry
* @param source
* @return
*/
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 如果名为org.springframework.aop.config.internalAutoProxyCreator的bean已经注册
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//已经在册的ProxyCreator与当前期望的类型不一致,则依据优先级进行选择
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 下面这两个方法findPriorityForClass()就是看看注册表registry中的key为AUTO_PROXY_CREATOR_BEAN_NAME的bean和
// 当前要注册 AnnotationAwareAspectJAutoProxyCreator 作比较。
// 比较 在 APC_PRIORITY_LIST 里面的三个类:
// InfrastructureAdvisorAutoProxyCreator.class
// AspectJAwareAdvisorAutoProxyCreator.class
// AnnotationAwareAspectJAutoProxyCreator.class
// 看一下那个索引下标index大,AnnotationAwareAspectJAutoProxyCreator的下标最大;
// 目的就是为了注册 AnnotationAwareAspectJAutoProxyCreator
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
//选择优先级高的ProxyCreator更新注册
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
// 如果注册表中没有对应的 ProxyCreator,就注册一个进去 cls是:
// org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
// 这是优先级 @Order(1) 这个注解的所用,或者对应的优先级标签的登记,这里设置的默认值。
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册进 ((DefaultListableBeanFactory) registry).beanDefinitionMap 中
// key : org.springframework.aop.config.internalAutoProxyCreator
// value : AnnotationAwareAspectJAutoProxyCreator
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
}
(2.) 获取注解上的属性信息;这里获取的 @EnableAspectJAutoProxy上的
// 2. 获取注解上的属性信息;这里获取的 @EnableAspectJAutoProxy上的 AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
这个没啥好介绍的,就是利用注解工具类,获取 @EnableAspectJAutoProxy上的的两个属性:
proxyTargetClass
、exposeProxy
(3.)设置标签
proxyTargetClass
、exposeProxy
// 3. 设置标签 if (enableAspectJAutoProxy != null) { // 3.1 获取并处理proxy-target-class属性: // false表示使用java原生动态代理; // true表示使用CGLib动态. // 但是对于一些没有接口实现的类来说,即使设置为false也会使用CGlib进行代理. if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } // 3.2 获取并处理expose-proxy标签,实现对于内部方法调用的AOP增强 if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } }
还是在AopConfigUtils类中;主要就两个方法:
AopConfigUtils#forceAutoProxyCreatorToUseClassProxying()
、AopConfigUtils#forceAutoProxyCreatorToExposeProxy()
可以以 proxyTargetClass
属性为例,可以看到,先找前面注册AnnotationAwareAspectJAutoProxyCreator
的BeanFactory,这里建议 debug 一下看看definition类型,找打里面 beanDefinitionMap
属性,然后找到 AnnotationAwareAspectJAutoProxyCreator
对应的 map 键值对,为其add
属性,exposeProxy
也一样。
public abstract class AopConfigUtils {
/**
* 设置proxy-target-class属性为true.
* false表示使用java原生动态代理;
* true表示使用CGLib动态.
* @param registry
*/
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// 这可以从 ((DefaultListableBeanFactory) registry).beanDefinitionMap 中,
// 找到前面注册的Bean -> AnnotationAwareAspectJAutoProxyCreator
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 为其添加属性 proxyTargetClass,并置为 true
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
/**
* 设置 exposeProxy为true.
* @param registry
*/
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
}
这里仅仅是注册了 AnnotationAwareAspectJAutoProxyCreator
,怎么用,不要着急,后面会用。(下面先把配置文件方式的注册也给介绍了。)
2.2 基于配置文件方式注册
AopNamespaceHandler
该类只有一个方法:init()
,通过该类的名字我们可以知道,该类是AOP 命名空间处理器,就是就出注册处理AOP 配置文件节点的各种类型的 解析器。
下面解析器:1,2,4 注册到 org.springframework.beans.factory.xml.NamespaceHandlerSupport#parsers
map上;
3 不能算是解析是,他是当前AOP的一个装饰器,将其装饰成符合 配置作用域的bean; 注册到 org.springframework.beans.factory.xml.NamespaceHandlerSupport#decorators
map上。
这3个解析器,都是实现了 org.springframework.beans.factory.xml.BeanDefinitionParser#parse
方法,解析器注册之后,Bean 在注册相应通知实例的时候,就会调用该方法对节点解析。关于Spring IOC注册如何解析,这不AOP这篇文章的范畴里面。
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* 该方法将 config,aspectj-autoproxy,scoped-proxy,spring-configured 注册到BeanDefinitionParsers
*/
@Override
public void init() {
// In 2.0 XSD as well as in 2.5+ XSDs
// 1. 这种 解析的是 <aop:aspect id="hamburgerAspect" ref="hamburgerAspectConfig"> 所有切面,通知xml方式配置的。
// 我们可以进入 ConfigBeanDefinitionParser中
// 该类中有各种 有关aop配置文件的标签名
// 还有各种标签解析方法,如:切面、切入点、增强器、通知解析器
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
// 2. 这种 解析的是 <aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="false"/> ,切面还是@AspecdJ注解方式配置的
// 注册 <aspectj-autoproxy/>标签及其解析器
// 该方法,我们可以看到,将AspectJAutoProxyBeanDefinitionParser解析器注册(put)到 NamespaceHandlerSupport 的 parsers map中
// 进入AspectJAutoProxyBeanDefinitionParser看其主要的parse() 解析方法
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
// 3.
// proxy,它代理的工作就是——暴露这个bean令其符合其自身作用域。
// 如当前回话:session作用域
// <bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
// <aop:scoped-proxy/>
// </bean>
//
// <bean id="userManager" class="com.foo.UserManager">
// <property name="userPreferences" ref="userPreferences"/>
// </bean>
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// 4.
// <context:spring-configured/> 主要是通过Spring管理AnnotationBeanConfigurerAspect切面,具体的工作由该切面完成。
// Only in 2.0 XSD: moved to context namespace in 2.5+
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
(1.)这种 解析的是
<aop:aspect id="hamburgerAspect" ref="hamburgerAspectConfig">
,所有切面、通知xml方式配置的。真正的xml配置方式的解析类// 1. 这种 解析的是 <aop:aspect id="hamburgerAspect" ref="hamburgerAspectConfig"> 所有切面,通知xml方式配置的。 // 我们可以进入 ConfigBeanDefinitionParser中 // 该类中有各种 有关aop配置文件的标签名 // 还有各种标签解析方法,如:切面、切入点、增强器、通知解析器 registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
-
进入
org.springframework.aop.config.ConfigBeanDefinitionParser#parse
方法class ConfigBeanDefinitionParser implements BeanDefinitionParser { @Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); // ★★★★1. 这里往下一直走,我们会发现,我们还会注册 AnnotationAwareAspectJAutoProxyCreator.class★★★ configureAutoProxyCreator(parserContext, element); List<Element> childElts = DomUtils.getChildElements(element); for (Element elt: childElts) { String localName = parserContext.getDelegate().getLocalName(elt); if (POINTCUT.equals(localName)) { // 切入点解析 parsePointcut(elt, parserContext); } else if (ADVISOR.equals(localName)) { // 增强器解析 parseAdvisor(elt, parserContext); } else if (ASPECT.equals(localName)) { // 切面解析 parseAspect(elt, parserContext); } } parserContext.popAndRegisterContainingComponent(); return null; } }
-
跟一下:
configureAutoProxyCreator(parserContext, element);
/** * 配置支持 <aop:config/>标签创建的BeanDefinitions所需的自动代理创建者。如果 proxy-target-class 属性设置为"true",则将强制类代理。 * @see AopNamespaceUtils */ private void configureAutoProxyCreator(ParserContext parserContext, Element element) { AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); } // -> 往下跟 AopNamespaceUtils#registerAspectJAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) /** * xml方式 <aop:aspect id="hamburgerAspect" ref="hamburgerAspectConfig"> */ public static void registerAspectJAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) { // 往下跟 这个 BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); } @Nullable public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, @Nullable Object source) { // 往下跟 这个 return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); } // ------->就来到了公共的 注册 AnnotationAwareAspectJAutoProxyCreator.class的方法 org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired
-
(2.)这种 解析的是
<aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="false"/>
,切面还是@AspecdJ注解方式配置的。所以还是下面 AspectJAutoProxyBeanDefinitionParser() 的解析过程,走的还是 注解配置方式的注册流程
// 2. 这种 解析的是 <aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="false"/> ,切面还是@AspecdJ注解方式配置的 // 注册 <aspectj-autoproxy/>标签及其解析器 // 该方法,我们可以看到,将AspectJAutoProxyBeanDefinitionParser解析器注册(put)到 NamespaceHandlerSupport 的 parsers map中 // 进入AspectJAutoProxyBeanDefinitionParser看其主要的parse() 解析方法 registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
-
进入
AspectJAutoProxyBeanDefinitionParser
的parser()
方法:class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser { /** * 解析 * @param element * @param parserContext */ @Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 1. 注册标签解析器,默认使用 AnnotationAwareAspectJAutoProxyCreator AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); // 2. 解析 <aop:include> 子标签,记录到 BeanDefinition 到 includePatterns 属性中 extendBeanDefinition(element, parserContext); return null; } }
-
进入 1. 注册标签解析器,默认使用
AnnotationAwareAspectJAutoProxyCreator
// 1. 注册标签解析器,默认使用 AnnotationAwareAspectJAutoProxyCreator AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
-
进入方法:
public abstract class AopNamespaceUtils { public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { // 1. 注册默认的 AnnotationAwareAspectJAutoProxyCreator 到 当前的registry中 BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement)); // 2.获取并处理标签的proxy-target-class和expose-proxy属性 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); // 3.注册组件,并发布事件通知 registerComponentIfNecessary(beanDefinition, parserContext); } }
-
进入1. 注册默认的 AnnotationAwareAspectJAutoProxyCreator 到 当前的registry中
进入到这里,我们就发现,这里注册的方法 和 注解方式 注册的流程是公共的的了 ,最终都会走到 org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired() 该方法进行注册。
// 1. 注册默认的 AnnotationAwareAspectJAutoProxyCreator 到 当前的registry中 BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
-
2.就没啥了,添加 标签中的 两个属性,还是解释一下吧;解析的是下面的标签里面的两个属性
<aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="false"/>
-
-
-
2.3 注册总结
这里我们总结一下 注解方式 和 配置文件方式:
注解是基于 @AspectJ
;有两种方式,一种是 @EnableAspectJAutoProxy
纯注解方式;一种是 切面用注解,在配置文件中配置 <aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="false"/>
启动AOP自动代理。
配置文件方式:就是纯解析xml标签节点方式。
但是最终我们发现,都会走到 org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired
方法来注册 AnnotationAwareAspectJAutoProxyCreator.class
三、构建 通知链,创建代理,并注册到beanFactroy中
首先,我们要明白上一步注册意义,目的是 注册 AnnotationAwareAspectJAutoProxyCreator.class
;
而,该类在不按功能划分的角度,从垂直角度看类关系看:找到它的顶级父类 AbstractAutoProxyCreator
从该类中可以找到Bean初始化之后的后置处理方法:(这里也就是注册之后,这里处理 目标方法(就是我们要增强器的方法))
我们也要知道,后置处理方法, AOP在这里做的事情就是:执行步骤中的 2,3,4步。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
// 如果beanName不为空则直接使用beanName(FactoryBean则使用&{beanName}),否则使用bean的className
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 尝试对bean进行增强,创建返回增强后的代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 已经处理过,直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 不需要进行增强的bean实例,直接跳过
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 对于AOP的基础支撑类,或者指定不需要被代理的类,设置为不进行代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 3.1 获取当前bean的 增强器,通知,拦截器列表
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果返回的不是空,说明被代理了。
// 则 基于获取的Advisor为当前bean创建代理对象
if (specificInterceptors != DO_NOT_PROXY) {
// cacheKey 是被增强的类, 该类的拦截器(通知)如果不为空,那么这里就是TRUE
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 3.2 创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 3.3.1 放进盛放代理对象的 map
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 3.3.2 盛放包装的 增强器map
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
3.1 获取当前bean的通知列链
大致分为下面4步骤:
- 1、调用 findCandidateAdvisor方法,找出候选的 通知列表;
- 2、从候选列表中筛选出 可以应用于当前bean的 通知列表;
- 3、为了添加一个 ExposeInvocationInterceptor拦截器作为 通知链的头一个;
- 4、对通知链排序。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
// 进入该方法
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 是个空方法,由子类实现:
// 这里有两个子类:BeanNameAutoProxyCreator、AbstractAdvisorAutoProxyCreator
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
@Nullable TargetSource customTargetSource) throws BeansException;
}
我们进入:AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean()
方法
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
@Nullable
private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass,
String beanName,
@Nullable TargetSource targetSource) {
// 进入,看这个核心流程
// 查找该bean对应的所有符合条件的Advisors(增强器)
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
// 这个 null值是 父类AbstractAutoProxyCreator的
return DO_NOT_PROXY;
}
return advisors.toArray();
}
/**
* Find all candidate Advisors to use in auto-proxying. 查找所有用于自动代理的候选Advisor(增强器)。
* @return the List of candidate Advisors 返回候选增强器列表
*/
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1. 调用 findCandidateAdvisor方法,找出候选的 通知列表
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2. 从候选列表中筛选出 可以应用于当前bean的 通知列表
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 3. 这里就是为了添加一个 ExposeInvocationInterceptor拦截器作为 通知链的头一个。
extendAdvisors(eligibleAdvisors);
// 对Advisor进行排序
if (!eligibleAdvisors.isEmpty()) {
// 4. 对通知链排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
// 3. 该类的一个空方法,有子类实现,只有一个子类:AspectJAwareAdvisorAutoProxyCreator 就是我们注册那个类
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
}
}
3.1.1 调用 findCandidateAdvisor方法,找出候选的 通知列表
这个方法,取的是缓存 cachedAdvisorBeanNames
bean对应的 通知链;或者去beanFactory中去找通知链,并缓存到cachedAdvisorBeanNames
中。
这里开始会有一个: beanName 为 :org.springframework.context.event.internalEventListenerProcessor
的,这个 就是 AnnotationAwareAspectJAutoProxyCreator
注册到Spring Bean中的 key
值,通过它,利用该方法可以找到对应的切面-通知类列表,注意,这里会缓存,当 beanName
是我们 的目标类(被AOP代理的类)的时候,下下步findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
就会从这个候选列表中找到可以匹配的通知列表。
这里是 :注意此时通知的类型:InstantiationModelAwarePointcutAdvisorImpl
//1. 调用 findCandidateAdvisor方法,找出候选的 通知列表
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 方法位置:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
/**
* Find all candidate Advisors to use in auto-proxying. 查找所有用于自动代理的候选Advisor(增强器)。
* @return the List of candidate Advisors 返回候选增强器列表
*/
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
// 进入该方法
return this.advisorRetrievalHelper.findAdvisorBeans();
}
// 方法位置 org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already. 确定advisor bean名称列表(如果尚未缓存)。
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
// 不要在这里初始化FactoryBeans:我们需要让所有常规Bean保持未初始化状态,以便让自动代理创建者应用于它们!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
// 这里 就是 通知类加到通知链里面
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
// 省略一万字....
}
}
}
return advisors;
}
findCandidateAdvisors();
方法走完,回到 3.1的主流程,进入2.
3.1.2 从候选列表中筛选出 可以应用于当前bean的 通知列表
// 2. 从候选列表中筛选出 可以应用于当前bean的 通知列表
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 方法位置:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
// 2.
/**
* Search the given candidate Advisors to find all Advisors that
* can apply to the specified bean.
* 从候选的增强器列表中找到 可以应用于指定的bean的所有增强器
* @param candidateAdvisors the candidate Advisors 候选列表
* @param beanClass the target's bean class 指定bean的class
* @param beanName the target's bean name 指定bean的name
* @return the List of applicable Advisors 返回可以应用于当前bean的增强器列表
* @see ProxyCreationContext#getCurrentProxiedBeanName()
*/
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors,
Class<?> beanClass,
String beanName) {
// 保存 当前代理的bean实例的名称 到当前代理创建的上下文中,(用ThreadLocal保存)
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// ★★ 进入该方法
// 去找符合的当前bean的增强器
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
// 上面保存当前的beanName,在去找到符合的增强器之后,用完,这里将ThreadLocal置为null
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
// 进入该方法 org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply
/**
* 从候选的Advisors列表知道适用于 当前bean的 增强器
* @param candidateAdvisors 候选的Advisors增强器
* @param clazz 目标类
* @return 从候选的Advisors列表知道适用于 当前bean的 增强器
* (may be the incoming List as-is)
*/
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
// 为空直接返回
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
// 盛放最终的筛选结果
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
// 判断 每一个候选的增强器 是否可以应用于当前的bean(targetClass)
// 如果可以就加入 eligibleAdvisors
// canApply(candidate, clazz)就是用于 判断 每一个候选的增强器 是否可以应用于当前的bean(targetClass)
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
// 还不知道 canApply(candidate, clazz, hasIntroductions) 这个有啥区别,先不管了。
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
3.1.3 为了添加一个 ExposeInvocationInterceptor拦截器作为 通知链的头一个
// 3. 这里就是为了添加一个 ExposeInvocationInterceptor拦截器作为 通知链的头一个。
extendAdvisors(eligibleAdvisors);
解释一下:为啥让 ExposeInvocationInterceptor拦截器作为 通知链的头一个
在Spring AOP中,ExposeInvocationInterceptor拦截器通常作为通知链的头一个拦截器,其作用是将当前的方法调用信息暴露给其他的切面通知。当一个方法被代理时,Spring AOP会创建一个代理对象,并在代理对象的方法调用前后执行切面通知。
而ExposeInvocationInterceptor拦截器的作用是在方法调用前将当前的方法调用信息绑定到ThreadLocal中,以便其他的切面通知可以获取到该方法调用信息。
通过将ExposeInvocationInterceptor拦截器作为通知链的头一个拦截器,可以确保在其他的切面通知执行时,可以通过AopContext.currentInvocation()方法获取到当前的方法调用信息。这样其他的切面通知就可以获取到方法的参数、方法名、目标对象等相关信息,从而实现更灵活的切面编程。
需要注意的是,为了能够使用ExposeInvocationInterceptor拦截器,目标对象必须实现Spring的AopProxy接口,并且在配置AOP时需要将ExposeInvocationInterceptor拦截器添加到通知链的头部。
3.1.4 对通知链排序
// 4. 对通知链排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
3.1
getAdvicesAndAdvisorsForBean()
流程走完,回到wrapIfNecessary(bean, beanName, cacheKey)
;继续 3.2
3.2 创建代理对象
大致分为下面6步骤:
- 1、创建代理工厂;
- 2、设置
proxyTargetClass
值; - 3、为了添加一个 ExposeInvocationInterceptor拦截器作为 通知链的头一个;
- 4、将通知其构建成Advisor类型;
- 5、创建代理对象;
- 6、缓存代理。
// 3.2 创建代理对象
Object proxy = createProxy( bean.getClass(),
beanName, specificInterceptors,
new SingletonTargetSource(bean));
// 方法位置:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
/**
* Create an AOP proxy for the given bean. 给 给定的bean创建 AOP代理
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors ★当前bean的 增强器列表 (所以这里参数命名为:特殊的拦截器)
* @param targetSource the TargetSource for the proxy, already pre-configured to access the bean
* @return the AOP proxy for the bean 返回该bean的AOP代理
* @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);
// 3.2.1
// 这个就是看我们在 aop配置文件或者 @EnableAspectJAutoProxy 的参数 proxyTargetClass是否为 true;
// 如果为true:就是用CGLIB代理
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 3.2.2
// buildAdvisors 为了将增强器其构建成Advisor类型
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) { // 这里表明已经对增强器、通知做前置过滤了,表明增强器列表都是 通知类了
// 这里会将 设置为true
proxyFactory.setPreFiltered(true);
}
// 3.2.3
return proxyFactory.getProxy(getProxyClassLoader());
}
3.2.1 proxyTargetClass 设置
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
- proxyTargetClass
- true
- 目标对象实现了接口 – 使用CGLIB代理
- 目标对象没有接口(只有实现类) – 使用CGLIB代理
- false
- 目标对象实现了接口 – 使用JDK动态代理机制(代理所有实现了的接口)
- 目标对象没有接口(只有实现类) – 使用CGLIB代理机制
- true
3.2.2 将通知其构建成Advisor类型
// buildAdvisors 为了将增强器其构建成Advisor类型
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 通知放入代理工厂中
proxyFactory.addAdvisors(advisors);
先说明一下,为什么要将增强器构建成Advisor类型;
在 (3.1.1)小结中, 我们我们说过,specificInterceptors
获取的候选的通知l列表中通知的类型是 InstantiationModelAwarePointcutAdvisorImpl
;
该类是个实现类:沿着该类往上找,可以发现该类就是 Advisor的子类,这个类,我们特殊介绍一下吧;下面的代码块,我们可以看到,该类的构造方法,初始化了通知(或者增强器)的各种属性,如:通知的方法,参数,优先级,工厂等等;再 着重介绍一个参数 instantiatedAdvice
:是初始化通知的实际类型。
class InstantiationModelAwarePointcutAdvisorImpl implements InstantiationModelAwarePointcutAdvisor,
AspectJPrecedenceInformation,
Serializable {
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrder,
String aspectName) {
this.declaredPointcut = declaredPointcut; // 通知对应的 切入点表达式类AspectJExpressionPointcut
this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); // 获取该通知所在的 切面类class
this.methodName = aspectJAdviceMethod.getName(); // 通知方法 的方法名
this.parameterTypes = aspectJAdviceMethod.getParameterTypes(); // 通知方法 的方法参数
this.aspectJAdviceMethod = aspectJAdviceMethod; // 通知方法
this.aspectJAdvisorFactory = aspectJAdvisorFactory; // 通知方法对应的切面工厂
this.aspectInstanceFactory = aspectInstanceFactory; // 通知方法对应的切面实例化工厂
this.declarationOrder = declarationOrder; // 该通知方法的 优先级
this.aspectName = aspectName; // 通知方法所在的 切面类
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { // 懒加载方式
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else { //单例方式的切面
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// instantiateAdvice(this.declaredPointcut)方法
// 将通知构建成对应类型:
// AspectJAroundAdvice 环绕 ,AspectJMethodBeforeAdvice 前置通知,AspectJAfterAdvice 后置通知
// AspectJAfterReturningAdvice 后置返回通知, AspectJAfterThrowingAdvice 异常通知
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
}
3.2.3 创建代理对象
// 3.2.3
return proxyFactory.getProxy(getProxyClassLoader());
// 方法位置: org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
// 先看createAopProxy(),再看getProxy(classLoader)
return createAopProxy().getProxy(classLoader);
}
// 方法位置:org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy
protected final synchronized AopProxy createAopProxy() {
// 如果是第一次,代理标志这只为true;有监听器添加监听器
if (!this.active) {
activate();
}
// 创建代理
return getAopProxyFactory().createAopProxy(this);
}
//下面看 createAopProxy(this)
可以通过断点方式查看代理:(这里是CGLIB代理)
// 进入 createAopProxy()
// 这里就进入到代理的选择了
// 代码位置: org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 指定了 optimize:true 或者 proxyTargetClass:true 或者 没有实现接口
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.");
}
// 目标类是接口 或者 class是由代理类动态通过getProxyClass方法或newProxyInstance方法生成的
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则使用CGLIB代理
return new ObjenesisCglibAopProxy(config);
}
// 否则使用JDK动态代理
else {
return new JdkDynamicAopProxy(config);
}
}
}
好! createAopProxy()
返回的类型我们知道,我们就可以进入到 ObjenesisCglibAopProxy
类中 .getProxy(classLoader)
方法了。
class CglibAopProxy implements AopProxy, Serializable {
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + 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 (ClassUtils.isCglibProxyClass(rootClass)) {
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...
// 看,这里就是配置 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 ClassLoaderAwareUndeclaredThrowableStrategy(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);
}
}
}
如果是 JDK代理的.getProxy(classLoader)
方法 ,我们也看看吧:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 看,这里利用JDK方式创建代理
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
}
OK,代理对象完成,回到 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
方法,执行最后的 3.3.1。
3.2.4 缓存代理
// 3.3.1 放进盛放代理对象的 map
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
至此 wrapIfNecessary
方法走完,也就是完成了对 目标对象的增强(AOP方式增强代理对象);即完成对 当前的beanName被AOP代理的bean,完成后置处理。
下面就是我们利用代理对象执行目标方法。
四、执行目标方法时,转为执行代理
4.1 确定代理方式
下面两个截图,一个是:CGLIB方式,一个是JDK方式。
4.1.1 CGLIB方式
CGLIB方式利用的是 CglibAopProxy
里面的内部类 DynamicAdvisedInterceptor
的 intercept()
方法执行的。
class CglibAopProxy implements AopProxy, Serializable {
/**
* General purpose AOP callback. Used when the target is dynamic or when the proxy is not frozen.
* 通用AOP回调。当目标是动态的或代理未冻结时使用
*
* 这里基于 CGLIB代理 通过是实现 MethodInterceptor#intercept方法
*/
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
/**
* 这里执行代理方法,就是当我们执行我们的目标方法(被增强的方法)的时候,其实就是来到这里,执行的代理方法;
* 从拦截器链中执行 代理类,目标方法,目标方法参数,代理方法
*/
@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) {
// 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);
// 1、
// 这里是获取当前通知的 增强器(或者叫拦截器)链,其实就是 被代理方法method的 通知,拦截器之类的这些.
List<Object> 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.
// 检查我们是否只有一个InvokerInterceptor:也就是说,没有真正的通知,只有对目标的反射调用。
// 拦截器链为空,按直接当做一个普通的代理执行就行了。
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... 创建方法的调用
// 2、
// proceed()就进入到 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()方法,
// 利用责任链模式 处理 拦截器链执行代理方法
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);
}
// 通过 判断代理接口 暴露出去;
// 如果 属性 exposeProxy设置成了true,那就需要恢复AOP的代理上下文为执行代理之前的状态
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
4.1.2 JDK方式
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
/**
* Implementation of {@code InvocationHandler.invoke}.
* <p>Callers will see exactly the exception thrown by the target,
* unless a hook method throws an exception.
*/
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 省略一万字.............
// Get the interception chain for this method.
// 1、获取通知链
List<Object> 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()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 2、创建 ReflectiveMethodInvocation,并调用proceed()方法执行通知链
// 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();
}
// Massage return value if necessary.
// 对返回值处理
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
两种代理方式执行的过程大致相似;
主要就分了两步:
- 1、获取通知链;
- 2、执行通知链。
4.2 获取通知链
// 这里是获取当前通知的 增强器(或者叫拦截器)链,其实就是 被代理方法method的 通知,拦截器之类的这些.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 来到下面代码位置:org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
// 如果缓存中已经有目标类的通知链了,就直接返回了;没有了就是去获取,然后再放到缓存中
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 进入该方法
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
// 代码位置:org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
/**
* 构建拦截器链,并返回
* 可以是各种类型的拦截器;如:普通的通知类型的增强器;引介增强器等
*/
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length); //创建拦截器链长度
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); // 目标类
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass); // 判断 通知列表中是否包含匹配的引介。
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); // 这里是通知的适配器
// config.getAdvisors()我们就可以获取匹配目标方法的到通知列表,可以看下面图的Debug
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) { // 这里是我们正常的 通知类型
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); // 方法匹配器
//上面的mm类型是 TrueMethodMatcher类型,这里应该无论如何都是true
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
// 在getInterceptors()方法中创建新的对象实例不是问题,因为我们通常会缓存创建的链。
for (MethodInterceptor interceptor : interceptors) {
// 注意这里将通知构建成 InterceptorAndDynamicMethodMatcher,再添加到执行器链的。
// 为什么呢? 我们可以去 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()看看
// 在执行的时候,有一个是判断是该动态类型拦截器的if
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
// 我们的切面-通知方法 mm.isRuntime() = false,所以会走这里添加到通知链中。
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 增强器类型如果是 引介增强器
// 进入下面的流程时,我们假设是我们 a-spring-test-pro工程中,
// aopintroduction 包中demo: 自定义 引介增强器 CustomIntroductionInterceptor
else if (advisor instanceof IntroductionAdvisor) {
// 那么,这里会是 默认的DefaultIntroductionAdvisor
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
// 那么,ia.getClassFilter()是获取该引介增强器的类过滤器
// 那么,ia.getClassFilter().matches(actualClass) 恒为 true
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
// 那么, registry.getInterceptors(advisor)获取的就是 CustomIntroductionInterceptor
// 我们知道了 CustomIntroductionInterceptor
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else { // 其他类型的拦截器
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
}
config.getAdvisors()
我们就可以获取匹配目标方法的到通知列表:
OK,通知链获取完,下面就是精彩的执行部分了。回到主方法intercept()
或 invoke()
;
不论是CGLIB:
// proceed()就进入到 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()方法,
// 利用责任链模式 处理 拦截器链执行代理方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
不论是 JDK:
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target,
method, args,
targetClass, chain);
retVal = invocation.proceed();
一个 new CglibMethodInvocation
和 new ReflectiveMethodInvocation
,
但是都是调用的 org.springframework.aop.framework.ReflectiveMethodInvocation#proceed()
方法
4.3 执行通知链
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
protected final List<?> interceptorsAndDynamicMethodMatchers;
private int currentInterceptorIndex = -1;
/**
* 这里是利用 一个List链表存放 要被执行的拦截器,通过 数组下标的移动 和递归实现的 责任链模式。
* 可以看本人在学习 Mybatis源码时,Mybatis源码中对于 责任链模式的使用和本人找的demo案例:
* https://gitee.com/old_yogurt/mybatis-sources-learning
* mybatis-3-mybatis-3.5.2 工程中 plugin包中 ① InterceptorChain就是利用List+for循环实现责任链 ② base包是 demo案例
*/
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 从索引 -1开始,然后递增
// 当 拦截器链执行到最后一个时,调用 invokeJoinpoint方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 1、
// 利用反射执行方法
return invokeJoinpoint();
}
// 先执行++ 操作,再获取拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 可以看一下 InterceptorAndDynamicMethodMatcher里面的注释,封装了 拦截器
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
// 如果匹配,就利用该 对应的拦截器类型执行 要调用的方法
return dm.interceptor.invoke(this);
}
else {
// 动态匹配失败。
// 跳过此拦截器并调用链中的下一个拦截器。
// 递归
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 它是一个拦截器(仅仅是一个拦截器,不是 InterceptorAndDynamicMethodMatcher 类型的),
// 所以我们只需调用它本身的invoke方法执行即可:在构造这个对象之前,切入点将被静态地计算。
// 2、
// AspectJMethodBeforeAdvice
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
/**
* 使用反射调用连接点。子类可以覆盖此项以使用自定义调用。
* 可以进入子类:CglibAopProxy 的内部类 CglibMethodInvocation中对该方法的实现
*
* @return 连接点的返回值
* @throws Throwable if invoking the joinpoint resulted in an exception
*/
@Nullable
protected Object invokeJoinpoint() throws Throwable {
// 利用反射执行方法
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
}
先看一下 interceptorsAndDynamicMethodMatchers
属性,就是通知列表。
。。。这里有点难解释。
这里先不说通知链为啥是倒序的,流程走完再解释。
(1、)处位置,只有当递归进入到最底层,也就是索引下标为0时,执行的是我们目标方法的代码;
(2、)处位置是执行通知链的地方。
4.3.1 入栈
入栈,来到栈深度 1 :
currentInterceptorIndex = 0
// 方法位置:
public class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed(); //这里是又回到 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed() 拦截器链中
}
finally {
invocation.set(oldInvocation);
}
}
}
该方法目标,暴露当前目标方法:放到invocation
的当前线程中。
好,调用 mi.proceed();
回到 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
拦截器链中。
入栈,来到栈深度 2 :
此时 currentInterceptorIndex = 1
,对应 AspectJAfterThrowingAdvice
,栈深度2。
// 代码位置
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 执行方法
// 调用拦截器链 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
return mi.proceed();
}
catch (Throwable ex) {
// 注意这里是在 catch块中
if (shouldInvokeOnThrowing(ex)) {
// 调用 org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod() 通知基础类的方法
// 执行 异常通知方法
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
}
因为是 异常通知,所以异常通知发放在catch块中了;目前不论有没有异常,我们都先是执行 mi.proceed();
,回到 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
中,保留 catch
块中的 invokeAdviceMethod(getJoinPointMatch(), null, ex);
入栈,来到栈深度 3 :
此时 currentInterceptorIndex = 2
,对应 AspectJAfterThrowingAdvice
,栈深度3。
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
private final AfterReturningAdvice advice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed(); // 因为这里是 AfterReturning,所以,先执行 目标方法,或者环绕通知pj.proceed()下面部分的代码;
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); //再执行 AfterReturning
return retVal;
}
}
这里我们看到 后置返回通知,也是先回到 mi.proceed();
保留 this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
入栈,来到栈深度 4 :
此时 currentInterceptorIndex = 3
,对应 AspectJAfterAdvice
,栈深度4。
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 执行方法
// 调用拦截器链 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
return mi.proceed();
}
finally {
// 注意这里是 finally块中
// 调用 org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod() 通知基础类的方法
// 执行通知方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
}
这里我们看到 返回通知,也是先回到 mi.proceed();
保留 finally
块中的 invokeAdviceMethod(getJoinPointMatch(), null, null);
入栈,来到栈深度 5 :
此时 currentInterceptorIndex = 4
,对应 AspectJAroundAdvice
,栈深度5。
// 代码位置
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
// 这里会 new MethodInvocationProceedingJoinPoint,该类里面的proceed()处理执行环绕通知
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
// 获取1. 方法的连接点
JoinPointMatch jpm = getJoinPointMatch(pmi);
// 调用 org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod() 通知基础类的方法
// 2.
// 执行通知方法
return invokeAdviceMethod(pjp, jpm, null, null);
}
}
在切面中,环绕通知的方法,通常都会像下面这样写,这时候,上面通过(1.)获取当前方法的连接点,(2.)执行连点的调用,就会来到这里的环绕通知
方法:
先执行System.out.println("Around before ...");
然后调用 pj.proceed();
,
又回到 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
,
保留 System.out.println("Around after ...");
所以,我们就看到了,控制台打印的 Around before ...
。
这就是为什么环绕通知的前置处理先执行,@Before
在后面了。
/**
* 该通知会将目标方法封装起来,
* 并且 Around before ... -> 在 @Before前;
* Around after ... -> 在 @After前.
* @param pj
*/
@Around("pointCut()")
public void xxx(ProceedingJoinPoint pj) {
try {
System.out.println("Around before ...");
pj.proceed();
System.out.println("Around after ...");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
OK,回到 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
入栈,来到栈深度 6 :
此时 currentInterceptorIndex = 5
,对应 MethodBeforeAdviceInterceptor
,栈深度6。
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 1. 执行 前置通知,然后再接着下面的 proceed()往下走
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 2.
return mi.proceed();
}
}
1、就要执行 @Before
前置通知了。
2、回到mi.proceed();
入栈,来到栈深度 7 :
此时 currentInterceptorIndex = 6
, 栈深度7。
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1)
成立;利用反射执行目标方法。
// 该 if条件成立,
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 执行目标方法
return invokeJoinpoint();
}
至此,链中所有方法已经入栈,现在开始出栈。
4.3.2 出栈
来到栈深度 7 ,出栈:
(前置通知 @Before
执行完成出栈)
回到 @Before
前置通知的 MethodBeforeAdviceInterceptor#invoke
方法:看下图也可以看出来;
也就是要 回到 return mi.proceed();
来到栈深度 6 ,出栈:
(当前处于@Around
环绕通知中,要执行环绕通知的后半段)
往外出 :就是回到 org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
的这个位置:
return
执行完成;来到这里;执行环绕通知的后半段:
// 代码位置
public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, JoinPoint.StaticPart {
@Override
public Object proceed() throws Throwable {
// 调用的拦截器链,执行方法 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
// 执行(通知? 增强器? 引介? 拦截器?)都对。 环绕通知走这个。
return this.methodInvocation.invocableClone().proceed();
}
}
// 执行 this.methodInvocation.invocableClone().proceed();
// 来到环绕通知后面
@Around("pointCut()")
public void xxx(ProceedingJoinPoint pj) {
try {
System.out.println("Around before ...");
pj.proceed();
System.out.println("Around after ...");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
如下图所示,环绕通知后半段执行:
来到栈深度 5 ,出栈:
(此时处于 @After
后置通知)
后置通知 org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
,就来到了 前面入栈时候 保留的finally
块部分:
来到栈深度 4 ,出栈:
(后置返回通知 @AfterReturning
)
执行后置返回通知方法:
来到栈深度 3 ,出栈:
(这里来到 @AfterReturning
org.springframework.aop.aspectj.AspectJAfterThrowingAdvice#invoke
)
如果有异常,就会执行下面 catch
块的内容,如果没有就继续出栈了
来到栈深度 2 ,出栈:
(org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke
)
这里会恢复现场:
来到栈深度 1 ,出栈:
就回到了代理方法的位置,以CGLIB为例: org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept
;对后续处理。
再回到我们的 main
方法:
OK,整个通知链执行完成。。。 (完结撒花)
转载自:https://juejin.cn/post/7387323858237669391