概述
在之前的文章中,我们已经对 SpringAOP 的关键组件进行了描述,并且了解了其基本操作和流程。在本文中,我们将进一步深入源码,揭示 SpringAOP 的内部实现细节,理解其运行机制的每个环节,包括切面的织入方式、代理对象的创建过程、连接点的定位与匹配等。通过对完整运行流程的深入研究,我们能够更全面地理解 SpringAOP 的工作原理,并且能够更好地利用和扩展这一功能。
本专题共三篇文章,这是第二篇:
- 深入理解 SpringAOP(一):AOP 组件概述
- 深入理解 SpringAOP(二):AOP的执行流程;
- 深入理解 SpringAOP(三):AspectJ支持;
一、代理生效时机
在前文,我们提到了代理基于 AbstractAutoProxyCreator
的子类生效,因此直接观察该类,我们可以注意到 AbstractAutoProxyCreator
中实现了 SmartInstantiationAwareBeanPostProcessor
,说明他可能在三个关键节点触发代理:
InstantiationAwareBeanPostProcessor
:在实例化阶段,即 bean 实例化前后;SmartInstantiationAwareBeanPostProcessor
:早期引用创建阶段,即在循环依赖中,当 bean 已实例化而未被初始化时,被其他依赖它的 bean 通过getEarlyBeanReference
方法从一级缓存中获取;BeanPostProcessor
:在初始化阶段,即 bean 完成初始化后,进行依赖注入与各种声明周期回调前后;
1、在实例化阶段
InstantiationAwareBeanPostProcessor
分别提供了 postProcessBeforeInstantiation
和 postProcessAfterInstantiation
两个方法用于介入 bean 的实例化流程,其中 AbstractAutoProxyCreator
实现了前者:
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;
}
}
// 如果用户指定的自定义的目标源,则尝试获取目标源并根据其创建代理
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource 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;
}
return null;
}
protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
// 如果有 beanName,则使用 beanName 作为 key
if (StringUtils.hasLength(beanName)) {
return (FactoryBean.class.isAssignableFrom(beanClass) ?
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
}
// 否则使用类型作为 key
else {
return beanClass;
}
}
这段代码的作用是在实例化Bean之前进行处理。它检查Bean是否需要被代理:
- 如果需要,根据自定义目标源创建代理对象,并返回代理对象;
- 如果不需要代理或者不存在自定义目标源,则直接返回
null
,即走正常的 bean 实例化逻辑;
它主要是用来在更灵活的创建代理目标的,一般我们并不会用到,因此这里了解即可。
2、作为早期引用被创建时
SmartInstantiationAwareBeanPostProcessor
提供了三个方法,AbstractAutoProxyCreator
实现了两个:
predictBeanType
:确认 bean 的类型,这里会直接获取代理对象的类型;getEarlyBeanReference
:获取对象早期引用,这里会通过wrapIfNecessary
尝试为 bean 创建代理对象;
在开始前,我们需要明确,什么是早期引用:
一般情况下,Spring 会在 bean 初始化完毕后才会基于该 bean 实例创建代理对象,但是在循环引用时,比如 beanA 依赖 beanB 依赖 beanA 的情况下,由于后创建的 beanB 需要依赖先创建的 beanA,而在此时先创建的 beanA 并未完成初始化,则此时后创建的 beanB 会通过一级缓存中的 ObjectFactory
,也就是 () → getEarlyBeanReference
方法提前获得基于 beanB 创建的代理对象(如果不需要代理则就是 beanA 本身),这就是早期引用。
不过,虽然是早期引用阶段,但是实际上在这里创建代理对象的逻辑是与正常的初始化后创建代理对象的逻辑基本一致的:
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
后文我们需要重点关注 wrapIfNecessary
方法,不过目前我们知道在这一步会创建代理对象即可。
3、在初始化阶段
SmartInstantiationAwareBeanPostProcessor
提供了两个方法,AbstractAutoProxyCreator
只实现了其中的 postProcessBeforeInstantiation
,在初始化前,它将为 bean 生成代理对象:
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;
}
与 getEarlyBeanReference
基本一致,都是基于 wrapIfNecessary
完成的,只不过是时机不同。正常需要代理的 bean 会在这里被替换为代理对象。
二、创建代理对象前的准备
知道了代理对象在何时被创建,也大概了解了相关的基本组件,现在我们需要真正的了解代理对象是如何被创建的,通知、切点和通知器这些组件将会在这个过程中扮演怎样的角色。
而 wrapIfNecessary
方法则是入口,在这个方法中,spring 会确认 bean 是否需要被代理,如果是就为其创建代理对象:
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;
}
// 为 bean 获取需要的通知器
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 注明该 bean 已经被代理
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 为其创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
1、为 bean 获取通知器
当获得一个 bean 时,spring 会通过 getAdvicesAndAdvisorsForBean
方法为这个 bean 获得它需要的通知器与通知,在 AbstractAutoProxyCreator
它是个空实现,AbstractAdvisorAutoProxyCreator
实现了
@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();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获取 spring 容器中所有的 Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
// 获取 spring 容器中所有的 Advisor
// 就是字面意思,从 BeanFactory 中实例化所有 Advisor 并返回
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
// 一个类似 TransactionSynchronizationManager 的上下文,用于记录当前正在创建代理对象的 bean 的一些信息
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
// 将其从上下文中移除
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
整体逻辑比较直观,总共就三步:
- 从
BeanFactory
加载并获取所有的Advisor
; - 从这些
Advisor
中筛选出 bean 需要的部分; - 将这些
Advisor
按@Order
或者Ordered
接口排序;
值得一提的是,在 AnnotationAwareAspectJAutoProxyCreator
中,它对 findCandidateAdvisors
进行了重写,在原有逻辑的基础上添加了基于 AspectJ
生成的 Advisor
,这里暂且先知道即可。
2、筛选匹配通知器
这里我们额外的看一下 AopUtils.findAdvisorsThatCanApply
方法,它揭露了通知器 Advisor
是如何判断是否需要为这个 bean 应用切点的:
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 processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
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 pca) {
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// 获取方法匹配器
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
// 如果可以同时针对方法和类型匹配
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
// 获取这个 bean 中直接声明的方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
// 根据方法、或者同时根据方法与类型判断是否要应用通知
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
这里大体处理了两类匹配逻辑:
- 如果通知器是
IntroductionAdvisor
类型,则通过通知器的ClassFilter
进行类型匹配; - 如果通知器是
PointcutAdvisor
类型,则通过通知器的Pointcut
切点中的ClassFilter
与MethodMatcher
分别对类型和类中的方法进行匹配。不过,针对MethodMatcher
又分两种情况:MethodMatcher
是IntroductionAwareMethodMatcher
类型,说明支持同时根据方法和 bean 的类型进行匹配;- 如果不是,则说明只支持根据方法进行匹配;
3、确认代理类型
让我们回到 wrapIfNecessary
,现在我们得到了所有可以作用于 bean 上的 Advisor
,接下来就需要根据这些 Advisor
去创建代理对象:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// ... ...
// 获取可作用于 bean 的 Advisor
// 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;
}
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);
}
// 根据 ProxyConfig(就是 AbstractAutoProxyCreator 本身)创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 如果需要基于目标类而不是其接口代理(即这个代理类没实现接口)
// 并且他们已经被 jdk 代理了(比如 Annotation 或者 Mybatis 的 Mapper),或者是根据 lambda 生成的匿名内部类
// 那么生成的代理类需要实现这些接口类型
if (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
// 其他情况下,根据 beanDefinition 中的 preserveTargetClass 属性
// 判断是否要直接基于这个类而不是其接口创建代理对象,简而言之,就是要不要走 CGLib 代理
else {
// No proxyTargetClass flag enforced, let's apply our default checks...
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
// 否则直接从这个类实现的接口中寻找可以用于代理的接口
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 创建 Advisor
// 一般情况下,这里就是各种 Advisor,不过也可能混有用于支持 AspectJ 的特殊对象,因此需要在这里统一处理
// 转为 Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
// 是否要启用 advisor 的预过滤,在 AbstractAutoProxyCreator 中总是返回 false
// 因此我们可以认为总是为 true
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);
}
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
// 确认接口是否满足下列条件,如果是那就使用它作为代理接口:
// 1、是否不为 Aware 这样的 Spring 回调接口
// 2、是否不为 cglib.proxy.Factory 这样的内部接口
// 3、是否有定义抽象方法(如果没有抽象方法那自然也没必要代理了)
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
// 如果找到了代理接口,说明需要基于接口代理
// 那就让代理对象实现所有的接口
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
// 如果没有找到代理接口,那就让他基于对象本身的类型生成代理
else {
proxyFactory.setProxyTargetClass(true);
}
}
暂且忽略代理工厂 ProxyFactory
中的逻辑,这里主要做了这么个判断:
- 如果
proxyFactory
设置了proxyTargetClass
标志为true
,则说明要使用目标类(target class)作为代理的基础。在这种情况下,如果目标类是JDK动态代理的代理类或者是 Lambda 表达式生成的匿名内部类,则需要特殊处理,即通过遍历目标类的接口,将这些接口添加到代理工厂中,以保证代理对象具备这些接口的方法; - 如果
proxyFactory
的proxyTargetClass
标志没有设置为true
,则执行下面的逻辑。这表示没有显式要求使用目标类作为代理基础,并且可以根据一些默认规则进行判断:
a. 如果根据默认规则确定应该使用目标类作为代理基础,则将proxyTargetClass
标志设置为true
,即需要进行 CGLib 代理;
b. 如果不满足使用目标类作为代理基础的条件,则根据目标类的接口情况来设置代理工厂的接口。通过调用evaluateProxyInterfaces(beanClass, proxyFactory)
方法,根据目标类的接口信息,将适合的接口添加到代理工厂中;
4、适配通知器
另外,在 createProxy
中,会调用 buildAdvisors
去适配通知器,这是虽然一般情况下输入的 specificInterceptors
大部分都是 Advisor
,不过也可能有一些其他的类型需要特殊处理,比如大家都很熟悉的 MethodInterceptor
,它只实现了 Advice
接口,因此需要在这里被适配为 DefaultPointcutAdvisor
。
总而言之,在创建代理对象前,需要调用适配器将里面入参的 Object
类型的数组 specificInterceptors
,全部确保转为 Advisor
:
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// 有些拦截器是直接通过把 beanName 设置到 AbstractAutoProxyCreator 注册的
// 因此此处需要将他们直接取出来
// Handle prototypes correctly...
Advisor[] commonInterceptors = resolveInterceptorNames();
// 收集所有可用的拦截器
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
if (specificInterceptors.length > 0) {
// specificInterceptors may equal PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
allInterceptors.addAll(Arrays.asList(specificInterceptors));
}
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
// 调用通知器适配器注册表 advisorAdapterRegistry,尝试将所有的拦截器对象适配为通知器
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
private Advisor[] resolveInterceptorNames() {
BeanFactory bf = this.beanFactory;
ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
List<Advisor> advisors = new ArrayList<>();
for (String beanName : this.interceptorNames) {
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
Object next = bf.getBean(beanName);
advisors.add(this.advisorAdapterRegistry.wrap(next));
}
}
return advisors.toArray(new Advisor[0]);
}
这里我们需要看一下 AdvisorAdapterRegistry
的唯一一个实现类 DefaultAdvisorAdapterRegistry
的 wrap
方法:
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
// 已经是 Advisor 了,直接返回
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 没有实现 Advice 接口,直接抛异常
if (!(adviceObject instanceof Advice advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
// 是方法拦截器,这是最常见的实现
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
// 不是上述两者,则调用 AdvisorAdapter 链尝试将其适配为 Advisor
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
这里的逻辑还是比较直白的:
- 如果已经是
Advisor
了,就直接返回; - 如果不是
Advisor
,那必须是Advice
,否则直接抛异常; - 如果它是
MethodInterceptor
,那就将其适配为DefaultPointcutAdvisor
(可能是考虑到 spring 中几乎九成九的 AOP 都是基于MethodInterceptor
实现的,因此这里直接专门提出来了); - 如果是其他情况,就调用适配器链,找到一个支持处理这个拦截器的
AdvisorAdapter
去对它做适配;
三、创建代理对象
经历了一番波折,现在我们得到了所有最终可用的 Advisor
,以及在 ProxyFactory
设置好了代理类要实现哪些类型,现在我们看看 ProxyFactory.getProxy
是如何创建代理对象的:
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 获取 AOP 代理工厂,默认为 DefaultAopProxyFactory
return getAopProxyFactory()
.createAopProxy(this);
}
1、确认代理方式
在默认情况下,getAopProxyFactory
会获得一个 DefaultAopProxyFactory
实例,在 createAopProxy
方法中,会根据各种条件决定要使用何种方式生成代理:
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
private static final long serialVersionUID = 7930414337282325166L;
@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.");
}
// 如果在上文获取到的代理类型,若满足下述任意条件,则使用 JDK 代理:
// 1、代理的目标类是接口;
// 2、代理的目标类本身就是个代理类
// 3、代理的目标类是基于 Lambda 表达式生成的匿名内部类
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则基于 Cglib 代理
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
/**
* Determine whether the supplied {@link AdvisedSupport} has only the
* {@link org.springframework.aop.SpringProxy} interface specified
* (or no proxy interfaces specified at all).
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
这里主要做了这三层判断:
- 如果应用程序运行在 Native Image环境中(即原生镜像化环境,例如 GraalVM 的 Native Image 模式),则直接返回使用JDK动态代理
JdkDynamicAopProxy
。 - 如果配置中设置了优化标志
optimize
,或者配置中设置了proxyTargetClass
标志,或者没有提供用户自定义的代理接口(即没有明确指定要代理的接口),则需要进一步判断:
a. 如果目标类targetClass
为空,则抛出AopConfigException
异常,提示无法确定目标类;
b. 如果目标类是接口类型targetClass.isInterface()
,或者是JDK动态代理的代理类Proxy.isProxyClass(targetClass)
,或者是Lambda表达式生成的类ClassUtils.isLambdaClass(targetClass)
,则返回使用JDK动态代理;
c. 如果以上条件都不满足,即目标类既不是接口也不是代理类,那么返回使用CGLIB动态代理ObjenesisCglibAopProxy
。 - 如果以上条件都不满足,则默认使用JDK动态代理
JdkDynamicAopProxy
;
简而言之,仅当代理的目标类没有接口,且不是代理类的时候,才会使用 Cglib
基于子类生成代理对象,这也是为什么即使我们的 bean 没有实现任何接口,Spring 依然能够生成代理的原因。
2、创建代理类
现在,通过 ProxyFactory
中的 AopProxyFactory
,我们可能获得 JdkDynamicAopProxy
或者 ObjenesisCglibAopProxy
对象,我们以比较常见的 JdkDynamicAopProxy
为例,看看它是如何真正的创建代理对象的:
@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);
}
这里平平无奇的直接调用了 Proxy.newProxyInstance
,那么显然一切的奥秘都在最后作为 InvocationHandler
传入的这个 this
,也就是 JdkDynamicAopProxy
本身。
先看看它的成员变量和构造函数:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
// 代理对象的生成配置,即 AbstractAutoProxyCreator 本身
// 此处保存有该 bean 的 Advisor 与代理方法的映射关系,以及该代理对象实现的接口类型
// 本身也是一个 Advised,当我通过代理对象调用 Advised 接口中声明的方法时,都会转发到这里
private final AdvisedSupport advised;
// 代理对象要实现哪些接口
private final Class<?>[] proxiedInterfaces;
// 是否有重写 hashCode 或者 equals 方法
private boolean equalsDefined;
private boolean hashCodeDefined;
/**
* Construct a new JdkDynamicAopProxy for the given AOP configuration.
* @param config the AOP configuration as AdvisedSupport object
* @throws AopConfigException if the config is invalid. We try to throw an informative
* exception in this case, rather than let a mysterious failure happen later.
*/
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
// 确认是否有重新 hashCode 或者 equals 放方法
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
}
在创建代理前,它会先添加一些默认的接口:
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
if (specifiedInterfaces.length == 0) {
// No user-specified interfaces: check whether target class is an interface.
Class<?> targetClass = advised.getTargetClass();
if (targetClass != null) {
if (targetClass.isInterface()) {
advised.setInterfaces(targetClass);
}
else if (Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
advised.setInterfaces(targetClass.getInterfaces());
}
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
// 添加 SpringProxy、Advised 接口
List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3);
for (Class<?> ifc : specifiedInterfaces) {
// Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17)
if (!ifc.isSealed()) {
proxiedInterfaces.add(ifc);
}
}
if (!advised.isInterfaceProxied(SpringProxy.class)) {
proxiedInterfaces.add(SpringProxy.class);
}
if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) {
proxiedInterfaces.add(Advised.class);
}
// 如果通知器 DecoratingProxy,就让代理对象也实现 DecoratingProxy
if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) {
proxiedInterfaces.add(DecoratingProxy.class);
}
return ClassUtils.toClassArray(proxiedInterfaces);
}
3、代理方法
InvocationHandler.invoke
是代理对象拦截待执行方法的关键,在 JdkDynamicAopProxy
中,它区分了五类方法,并做了不同的处理,这里我们主要关注后续通过 getInterceptorsAndDynamicInterceptionAdvice
获取通知调用链的部分:
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 {
// 调用 eqlues 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
// 调用 hashCode 方法
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
// 如果调用的方法来自于 DecoratingProxy 接口
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 如果这个方法来自于 Advised 接口,那就调用 Advised
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
// 真正的调用的进行增强,即调用 AOP 植入的各种前置和后置放阿飞
Object retVal;
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);
// 获取拦截器链
// Get the interception chain for this method.
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()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
//
// 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);
}
}
}
4、获取拦截器链
通过 AdvisedSupport
(其实就是 ProxyFactory
)的 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;
}
其中,AdvisorChainFactory
默认只有 DefaultAdvisorChainFactory
一个实现类,因此我们直接看它的 getInterceptorsAndDynamicInterceptionAdvice
方法即可:
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.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
// 按顺序遍历通知器
for (Advisor advisor : advisors) {
// 1、如果基于方法切点拦截,则根据方法切点判断通知是否生效
if (advisor instanceof PointcutAdvisor pointcutAdvisor) {
// 由于 isPreFiltered 必定为 true,因此这里实际上就是看看方法切点是否支持处理这个类型的 bean
// Add it conditionally.
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 支持处理这个类型,那就根据方法或者方法与类型判断是否要执行该切点
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
// 通知生效
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
// 如果这个方法检查器是动态的,即每次调用的时候才检查是否生效,那就将其包装为 InterceptorAndDynamicMethodMatcher
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// /2、如果基于类拦截,则基于类确认该通知是否生效
else if (advisor instanceof IntroductionAdvisor ia) {
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
// 3、其他的情况,比如基于 AspectJ,直接将其包装为 MethodInterceptor
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
可以看到,这里主要是检查将各种不同类型的 Advisor
是否支持处理该类型的 bean,如果是,就将其转为 MethodInterceptor
,然后收集所有的拦截器凑成链后,返回给代理对象:
- 如果当前的
Advisor
是一个PointcutAdvisor
,即基于切点的通知器,那么:- 先根据切点的
ClassFilter
判断是否匹配成功,然后再根据节点的MethodMatcher
的类型,觉得要根据方法还是同时根据方法与类进行匹配; - 如果匹配成功,再判断
MethodMatcher
是否根据方法调用情况动态的决定是否匹配,若是则将其包装为InterceptorAndDynamicMethodMatcher
并添加到拦截器链;
- 先根据切点的
- 如果当前的
Advisor
是一个IntroductionAdvisor
,即引介增强器,那么根据类过滤器的匹配规则判断是否需要将它添加到拦截器链中; - 如果当前的
Advisor
不是上述两种类型,直接将它的拦截器数组添加到拦截器链中;
5、执行拦截器链
回到 invoke
方法,现在我们通过 getInterceptorsAndDynamicInterceptionAdvice
方法获取调用链后,就该真正的执行它的:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// ... ...
// 真正的调用的进行增强,即调用 AOP 植入的各种前置和后置放阿飞
Object retVal;
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);
// 获取拦截器链
// Get the interception chain for this method.
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()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 获取拦截器链
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// ... ...
}
执行上下文
其中,ReflectiveMethodInvocation
是一个包含了本次调用信息的一个执行上下文,它将在拦截器链中流转以完成全部的流程:
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
// 代理对象
protected final Object proxy;
// 原始对象与代理的方法
@Nullable
protected final Object target;
protected final Method method;
// 本次调用的参数
protected Object[] arguments;
// 调用对象的类型
@Nullable
private final Class<?> targetClass;
// 一些特殊的参数
@Nullable
private Map<String, Object> userAttributes;
// 拦截器链
protected final List<?> interceptorsAndDynamicMethodMatchers;
// 当前调用的拦截器链的下标
private int currentInterceptorIndex = -1;
protected ReflectiveMethodInvocation(
Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method); // 如果代理的是桥接方法,那就找到它的原始方法
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments); // 这里会根据方法入参类型适配一下入参
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers; // 拦截器链
}
}
调用拦截器链
当我们调用 ReflectiveMethodInvocation.proceed
方法的时候,实际上是会先调用拦截器链:
public Object proceed() throws Throwable {
// 如果没有拦截器,直接调用方法本身
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 获取拦截器,并让 currentInterceptorIndex + 1
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 如果是动态拦截器,就根据当前的调用参数判断是否要应用它
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher dm) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
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);
}
}
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
这个地方稍微有点绕,大概意思是这样的:
- 首先,
ReflectiveMethodInvocation
在内部维护了一个成员变量currentInterceptorIndex
,代表了当前调用到第几个拦截器; - 每当调用了一个拦截器后,都会使
currentInterceptorIndex
加一,也就是说,每当调用一次proceed
方法,都相当于执行了一个拦截器; - 当
currentInterceptorIndex
等于拦截器链的长度减一时,意味着所有的拦截器都调用完毕,此时真正的调用被拦截的方法;
在这个基础上,每次调用拦截器前,都会做一次判断,如果拦截器是动态拦截器,就根据方法参数判断是否要调用它,否则就直接调用 processed
跳过这个拦截器。
这也就意味着,我们在拦截器中完成拦截操作后,是需要主动的调用 ReflectiveMethodInvocation.processed
方法的,这个时候就体现出了这种设计的精妙之处:
- 允许主动中断:只有调用
proceed
时,拦截器链才会继续往下走,否则可以直接中断整个调用流程; - 可以拦截调用结果:当调用
proceed
后,实际上会形成递归,这使得所有的拦截器都可以获取并处理方法的返回值;
总结
1、代理的创建时机
- 实例化前后:依靠
InstantiationAwareBeanPostProcessor
完成,不太常见; - 初始化后:依靠
BeanPostProcessor
完成,如果没有因为循环依赖导致 bean 被提前实例化,那么正常情况 bean 会在这时被代理; - 获取早期引用时:依靠
SmartInstantiationAwareBeanPostProcessor
完成,当需要被代理的 bean 由于循环依赖导致初始化前就要被其他 bean 获取时,会在这时被提前完成代理;
其中,后两者最终都会通过 AbstractAutoProxyCreator.wrapIfNecessary
完成代理对象的创建。
2、通知器的获取
当进入 wrapIfNecessary
方法后,在真正的创建代理对象前,需要通过AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean
方法获取可应用于代理对象的通知器。
该方法的具体实现位于 AbstractAdvisorAutoProxyCreator
中:
- 调用
findEligibleAdvisors
用于查出是否有可用的通知器; - 在
findEligibleAdvisors
方法中,通过findCandidateAdvisors
加载 spring 容器中的所有Advisor
,在AnnotationAwareAspectJAutoProxyCreator
中通过重写该方法,额外加载了一些基于AspectJ
的通知器; - 再调用
findAdvisorsThatCanApply
从所有的Advisor
中筛选出可应用于当前 bean 的通知器:- 如果通知器是
IntroductionAdvisor
类型,则通过通知器的ClassFilter
进行类型匹配; - 如果通知器是
PointcutAdvisor
类型,则通过通知器的Pointcut
切点中的ClassFilter
与MethodMatcher
分别对类型和类中的方法进行匹配。其中,若MethodMatcher
类型为IntroductionAwareMethodMatcher
,则支持同时根据方法与其类型进行匹配; - 如果通知器不是上述两者,则认为其必定可应用与当前 bean;
- 如果通知器是
经过上述流程后若当前 bean 没有任何可用的通知器,则说明其无需代理,否则需要通过通知器进行代理增强。
3、代理前的准备
获得可用的通知器后,将会调用 createProxy
方法真正的进入创建代理对象的逻辑中。
- 创建一个
ProxyFactory
用于后续创建代理对象; - 尝试推断代理对象的类型:
- 若
proxyFactory
设置了proxyTargetClass
标志为true
,则说明要使用目标类(target class)作为代理的基础。在这种情况下,如果目标类是 JDK 动态代理的代理类(比如Annotation
)或者是 Lambda 表达式生成的匿名内部类,则需要遍历目标类的接口,将这些接口添加到代理工厂中,以保证代理对象具备这些接口的方法; - 如果
proxyFactory
的proxyTargetClass
标志没有设置为true
,则执行下面的逻辑。这表示没有显式要求使用目标类作为代理基础,则:
a.应该使用目标类作为代理基础,则将proxyTargetClass
标志设置为true
,即需要进行 CGLib 代理;
b.不满足使用目标类作为代理基础的条件,则调用evaluateProxyInterfaces
方法,根据目标类的接口信息,将适合的接口添加到代理工厂中;
- 若
- 适配通知器:在这一步,大部分的
Advisor
都以及被搜集到了,不过仍有一些通知器需要在buildAdvisors
方法中进行适配或者特殊的处理:- 收集通用通知器:处了在容器中注册的通知器外,有另一部分通用通知器直接通过直接在
AbstractAutoProxyCreator
中登记beanName
的方法设置,此时需要根据beanName
将其从容器中取出; - 适配通知器:此时,已收集的通知器中混有多种类型的对象,因此需要通过
AdvisorAdapterRegistry.wrap
**方法将其中非Advisor
对象进行适配:- 如果已经是
Advisor
了,就直接返回; - 如果不是
Advisor
,那必须是Advice
,否则直接抛异常; - 如果它是
MethodInterceptor
,那就将其适配为DefaultPointcutAdvisor
; - 如果是其他类型的
Advice
,就调用适配器链,找到一个支持处理这个拦截器的AdvisorAdapter
去对它做适配;
- 如果已经是
- 收集通用通知器:处了在容器中注册的通知器外,有另一部分通用通知器直接通过直接在
4、创建代理对象
- 当在
ProxyFactory
中配置好了代理对象的类型、需要实现的接口类型、需要应用的通知器及其他配置后; ProxyFactory
将会在createAopProxy
方法中获取一个AopProxyFactory
(默认为DefaultAopProxyFactory
);- 接着调用
DefaultAopProxyFactory
的createAopProxy
方法,根据情况去创建一个AopProxy
对象:- 如果需要基于目标类代理,那么就使用 CGLib 代理,返回一个
ObjenesisCglibAopProxy
; - 如果需要基于接口代理,那么使用 JDK 的动态代理,返回一个
JdkDynamicAopProxy
;
- 如果需要基于目标类代理,那么就使用 CGLib 代理,返回一个
- 接着我们调用
AopProxy
的getProxy
方法,该方法将会真正的创建一个代理对象。
5、方法代理
对于 JDK 动态代理来说,用于生成代理的 InvocationHandler
即为 JdkDynamicAopProxy
本身,当我们调用代理对象的方法时,将会统一经过 invoke
方法。
其中,根据方法类型又分为三种类型:
equals
和hashCode
方法:若两方法没有在接口中重新定义,则直接按JdkDynamicAopProxy
去进行比较/获取哈希值;- 如果方法是
DecoratingProxy
或Advised
接口中声明的方法,则直接通过当前代理对象内部持有的相应实例进行调用; - 如果是普通方法,则在调用前后一次调用通知器中的
Advice
增强逻辑;
其中,对于普通方法,在首次调用 invoke
的时候,将会:
- 通过内部持有的
AdvisedSupport
对象(即Advised
的默认实现)的getInterceptorsAndDynamicInterceptionAdvice
方法获取相应的方法拦截器; - 然后
AdvisedSupport
将会通过内部的AdvisorChainFactory
(默认为DefaultAdvisorChainFactory
)的getInterceptorsAndDynamicInterceptionAdvice
方法创建方法拦截器链; - 在
DefaultAdvisorChainFactory
中,将会:- 先取出
AdvisedSupport
中存放的所有可应用于当前 bean 的通知器,然后遍历它们:- 如果当前的
Advisor
是一个PointcutAdvisor
,即基于切点的通知器,那么根据其持有的切点Pointcut
中的ClassFilter
与MethodMatcher
进行匹配; - 如果当前的
Advisor
是一个IntroductionAdvisor
,即引介增强器,那么根据类过滤器的匹配规则判断是否需要将它添加到拦截器链中; - 如果当前的
Advisor
不是上述两种类型,直接将它的拦截器数组添加到拦截器链中;
- 如果当前的
- 在获得的可用的通知器后,通过
AdvisorAdapterRegistry.getInterceptors
(此处的适配器注册表在上文也用于适配Advisor
)方法将其全部适配为MethodInterceptor
;
- 先取出
- 通过
DefaultAdvisorChainFactory
获取方法拦截器链后,将会将拦截器链与要增强的代理方法封装为一个方法调用对象MethodInvocation
(默认为ReflectiveMethodInvocation
); - 然后调用
MethodInvocation.processed
方法,此时将会调用链首的拦截器,接着拦截器再继续调用processed
方法,递归此步骤,直到整个调用链完成或者中断为止;