死磕Spring之AOP篇 - Spring AOP自动代理(三)创建代理对象
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读。
Spring 版本:5.1.14.RELEASE
在开始阅读 Spring AOP 源码之前,需要对 Spring IoC 有一定的了解,可查看我的 《死磕Spring之IoC篇 - 文章导读》 这一系列文章
了解 AOP 相关术语,可先查看 《Spring AOP 常见面试题) 》 这篇文章
该系列其他文章请查看:《死磕 Spring 之 AOP 篇 - 文章导读》
在前面的《Spring AOP 自动代理(一)入口》文章中,分析了 Spring AOP 自动代理的入口是 AbstractAutoProxyCreator 对象,其中自动代理的过程主要分为下面两步:
- 筛选出能够应用于当前 Bean 的 Advisor
- 找到了合适 Advisor 则创建一个代理对象, JDK 动态代理或者 CGLIB 动态代理
上一篇《Spring AOP 自动代理(二)筛选合适的通知器》文章分析了上面第 1
步的处理过程,先去解析出当前 IoC 容器所有 Advisor 对象,包括 Advisor 类型的 Bean 和从 @AspectJ
注解的 Bean 解析出来的 Advisor 对象;然后通过通过 ClassFilter 类过滤器和 MethodMatcher 方法匹配器筛选出能够应用于这个 Bean 的 Advisor 们,最后进行排序;不同的 AspectJ 根据 @Order
排序,同一个 AspectJ 中不同 Advisor 的排序,优先级:AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice
本文将会分析上面的第 2
的创建过程,如果这个 Bean 有合适的 Advisor,那么为这个 Bean 创建一个代理对象,我们一起来看看是如何创建代理对象的。
回顾
// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
/*
* <1> 如果当前 Bean 已经创建过自定义 TargetSource 对象
* 表示在上面的**实例化前置处理**中已经创建代理对象,那么直接返回这个对象
*/
if (StringUtils.hasLength(beanName)
&& this.targetSourcedBeans.contains(beanName))
{
return bean;
}
// <2> `advisedBeans` 保存了这个 Bean 没有必要创建代理对象,则直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/*
* <3> 不需要创建代理对象,则直接返回当前 Bean
*/
if (isInfrastructureClass(bean.getClass()) // 如果是 Spring 内部的 Bean(Advice、Pointcut、Advisor 或者 AopInfrastructureBean 标记接口)
|| shouldSkip(bean.getClass(), beanName)) // 应该跳过
{
// 将这个 Bean 不需要创建代理对象的结果保存起来
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// <4> 获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// <5> 如果有 Advisor,则进行下面的动态代理创建过程
if (specificInterceptors != DO_NOT_PROXY) {
// <5.1> 将这个 Bean 已创建代理对象的结果保存至 `advisedBeans`
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// <5.2> 创建代理对象,JDK 动态代理或者 CGLIB 动态代理
// 这里传入的是 SingletonTargetSource 对象,可获取代理对象的目标对象(当前 Bean)
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// <5.3> 将代理对象的 Class 对象(目标类的子类)保存
this.proxyTypes.put(cacheKey, proxy.getClass());
// <5.4> 返回代理对象
return proxy;
}
// <6> 否则,将这个 Bean 不需要创建代理对象的结果保存起来
this.advisedBeans.put(cacheKey, Boolean.FALSE);
// <7> 返回这个 Bean 对象
return bean;
}
在创建代理对象的过程中,上面方法的第 4
步尝试获取能够应用于当前 Bean 的 Advisor,该过程在上一篇文章中进行分析过,如果有 Advisor,则调用 createProxy(..)
方法创建代理对象
注意,这里传入的 TargetSource 是一个 SingletonTargetSource 对象,可获取目标对象,如下:
public class SingletonTargetSource implements TargetSource, Serializable {
private static final long serialVersionUID = 9031246629662423738L;
private final Object target;
public SingletonTargetSource(Object target) {
Assert.notNull(target, "Target object must not be null");
this.target = target;
}
@Override
public Class<?> getTargetClass() {
return this.target.getClass();
}
@Override
public Object getTarget() {
return this.target;
}
@Override
public void releaseTarget(Object target) {
// nothing to do
}
@Override
public boolean isStatic() {
return true;
}
}
创建代理对象的流程
-
创建一个 ProxyFactory 代理工厂对象,设置需要创建的代理类的配置信息,例如 Advisor 数组和 TargetSource 目标类来源
-
借助 DefaultAopProxyFactory 选择 JdkDynamicAopProxy(JDK 动态代理)还是 ObjenesisCglibAopProxy(CGLIB 动态代理)
-
当
proxy-target-class
为false
时,优先使用 JDK 动态代理,如果目标类没有实现可代理的接口,那么还是使用 CGLIB 动态代理 -
如果为
true
,优先使用 CGLIB 动态代理,如果目标类本身是一个接口,那么还是使用 JDK 动态代理
-
-
通过 JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy 创建一个代理对象
- JdkDynamicAopProxy 本身是一个 InvocationHandler 实现类,通过 JDK 的
Proxy.newProxyInstance(..)
创建代理对象 - ObjenesisCglibAopProxy 借助 CGLIB 的 Enhancer 创建代理对象,会设置 Callback 数组和 CallbackFilter 筛选器(选择合适 Callback 处理对应的方法),整个过程相比于 JDK 动态代理更复杂点,主要的实现在 DynamicAdvisedInterceptor 方法拦截器中
- JdkDynamicAopProxy 本身是一个 InvocationHandler 实现类,通过 JDK 的
AbstractAutoProxyCreator
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
:AOP 自动代理的抽象类,完成主要的逻辑实现,提供一些骨架方法交由子类完成
1. createProxy 方法
createProxy(..)
方法,为目标对象创建一个代理对象,如下:
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
// 为目标 Bean 的 BeanDefinition 对象设置一个属性
// org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass -> 目标 Bean 的 Class 对象
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// <1> 创建一个代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
// <2> 复制当前 ProxyConfig 的一些属性(例如 proxyTargetClass、exposeProxy)
proxyFactory.copyFrom(this);
/**
* <3> 判断是否类代理,也就是是否开启 CGLIB 代理
* 默认配置下为 `false`,参考 {@link org.springframework.context.annotation.EnableAspectJAutoProxy}
*/
if (!proxyFactory.isProxyTargetClass()) {
/*
* <3.1> 如果这个 Bean 配置了进行类代理,则设置为 `proxyTargetClass` 为 `true`
*/
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
/*
* <3.2> 检测当前 Bean 实现的接口是否包含可代理的接口
* 如没有实现,则将 `proxyTargetClass` 设为 `true`,表示需要进行 CGLIB 提升
*/
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
/*
* <4> 对入参的 Advisor 进一步处理,因为其中可能还存在 Advice 类型,需要将他们包装成 DefaultPointcutAdvisor 对象
* 如果配置了 `interceptorNames` 拦截器,也会添加进来
*/
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// <5> 代理工厂添加 Advisor 数组
proxyFactory.addAdvisors(advisors);
// <6> 代理工厂设置 TargetSource 对象
proxyFactory.setTargetSource(targetSource);
// <7> 对 ProxyFactory 进行加工处理,抽象方法,目前没有子类实现
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
// <8> 是否这个 AdvisedSupport 配置管理器已经过滤过目标类(默认为 false)
if (advisorsPreFiltered()) {
// 设置 `preFiltered` 为 `true`
// 这样 Advisor 们就不会根据 ClassFilter 进行过滤了,而直接通过 MethodMatcher 判断是否处理被拦截方法
proxyFactory.setPreFiltered(true);
}
// <9> 通过 ProxyFactory 代理工厂创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
该方法的处理过程如下:
- 创建一个 ProxyFactory 代理工厂
proxyFactory
- 复制当前对象的一些属性给
proxyFactory
(例如 proxyTargetClass、exposeProxy),当前 AbstractAutoProxyCreator 对象继承了 ProxyConfig - 判断是否类代理,也就是是否开启 CGLIB 代理,默认配置下为
false
,如果没有的话,进行下面处理- 如果这个 Bean 配置了进行类代理,则设置为
proxyTargetClass
为true
- 否则,检测当前 Bean 实现的接口是否包含可代理的接口,如没有实现,则将
proxyTargetClass
设为true
,表示需要进行 CGLIB 提升
- 如果这个 Bean 配置了进行类代理,则设置为
- 调用
buildAdvisors(..)
方法,对入参的 Advisor 数组进一步处理,会将不是 Advisor 类型的对象包装成 DefaultPointcutAdvisor 对象 proxyFactory
代理工厂添加 Advisor 数组proxyFactory
代理工厂设置 TargetSource 对象,用户获取目标对象- 对
proxyFactory
进行加工处理,抽象方法,目前没有子类实现 - 是否这个 AdvisedSupport 配置管理器已经过滤过目标类(默认为
false
)- 是的话设置
preFiltered
为true
,这样 Advisor 们就不会根据 ClassFilter 进行过滤了,而直接通过 MethodMatcher 判断是否处理被拦截方法
- 是的话设置
- 调用
proxyFactory
代理工厂的getProxy(@Nullable ClassLoader classLoader)
方法创建代理对象
这个过程不复杂,容易理解,其中第 4
步会再次对 Advisor 数组进一步处理,在第 9
步根据 proxyFactory
创建代理对象
buildAdvisors 方法
buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors)
方法,对 Advisor 数组进一步处理,如下:
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
// <1> 将配置的 `interceptorNames` 转换成 Advisor 类型(默认没有)
Advisor[] commonInterceptors = resolveInterceptorNames();
// <2> 将 commonInterceptors 与 specificInterceptors 放入一个集合
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
// 是否添加至最前面(默认为 true)
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
/*
* <3> 遍历 `specificInterceptors` 数组
*/
for (int i = 0; i < allInterceptors.size(); i++) {
// <3.1> 将不是 Advisor 类型的 Advice 或者 MethodInterceptor 包装成 DefaultPointcutAdvisor 对象
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
// <4> 返回构建好的 Advisor 数组
return advisors;
}
该方法的处理过程如下:
-
将配置的
interceptorNames
转换成 Advisor 类型(默认没有),得到commonInterceptors
数组,如下: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]); }
解析
interceptorNames
中对应的 Bean,并包装成 Advisor 类型(如果需要的话) -
将上一步获取到的
commonInterceptors
数组放入入参中的specificInterceptors
数组中 -
遍历
specificInterceptors
数组-
将不是 Advisor 类型的 Advice 或者 MethodInterceptor 包装成 DefaultPointcutAdvisor 对象
// DefaultAdvisorAdapterRegistry.java @Override public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { // Advisor 类型,直接返回 return (Advisor) adviceObject; } if (!(adviceObject instanceof Advice)) { // 非 Advice 接口,抛出异常 throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // MethodInterceptor 类型,包装成 DefaultPointcutAdvisor 对象 // So well-known it doesn't even need an adapter. return new DefaultPointcutAdvisor(advice); } for (AdvisorAdapter adapter : this.adapters) { // Check that it is supported. // 检查该 Advice 类型是否支持 if (adapter.supportsAdvice(advice)) { // 包装成 DefaultPointcutAdvisor 对象 返回 return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); }
-
-
返回构建好的 Advisor 数组
能够应用于这个 Bean 的 Advisor 们已经准备好了,那么接下来我们来看看 ProxyFactory 是如何创建代理对象的
2. ProxyFactory
org.springframework.aop.framework.ProxyFactory
,代理工厂,如下:
public Object getProxy(@Nullable ClassLoader classLoader) {
// <1> 先创建一个 AOP 代理类(JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy)
// <2> 根据 AOP 代理为目标 Bean 创建一个代理对象,并返回
return createAopProxy().getProxy(classLoader);
}
过程分为两步:
-
调用
createAopProxy()
方法,创建一个 AOP 代理类(JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy),如下:protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } // <1> 先获取 AOP 代理工厂,默认为 DefaultAopProxyFactory,只有这个实现 // <2> 然后通过它根据创建当前 AdvisedSupport 配置管理器创建一个 AOP 代理(JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy) return getAopProxyFactory().createAopProxy(this); }
-
然后调用 AOP 代理类的
getProxy(@Nullable ClassLoader classLoader)
方法获取代理对象
可以看到选择 JDK 动态代理还是选择 CGLIB 动态代理在 DefaultAopProxyFactory 中可以找到答案
3. DefaultAopProxyFactory
org.springframework.aop.framework.DefaultAopProxyFactory
,默认的 AOP 代理工厂,如下:
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
/*
* <1> 判断是否满足下面三个条件的其中一个
*/
if (config.isOptimize() // 需要优化,默认为 `false`
|| config.isProxyTargetClass() // 使用类代理,也就是使用 CGLIB 动态代理
|| hasNoUserSuppliedProxyInterfaces(config) // 目标类没有实现接口
) {
// <1.1> 获取目标类
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.");
}
/*
* <1.2> 如果目标类是一个接口或者是 java.lang.reflect.Proxy 的子类
* 则还是使用 JDK 动态代理,创建一个 JdkDynamicAopProxy 对象,传入 AdvisedSupport 配置管理器,并返回
*/
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// <1.3> 使用 CGLIB 动态代理,创建一个 ObjenesisCglibAopProxy 对象,传入 AdvisedSupport 配置管理器,并返回
return new ObjenesisCglibAopProxy(config);
}
// <2> 否则
else {
// 使用 JDK 动态代理,创建一个 JdkDynamicAopProxy 对象,传入 AdvisedSupport 配置管理器,并返回
return new JdkDynamicAopProxy(config);
}
}
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
创建 AOP 代理类的过程如下:
-
判断是否满足下面三个条件的其中一个,则进行下面的处理
需要优化,默认为
false
;使用类代理,也就是使用 CGLIB 动态代理,在前面的
AbstractAutoProxyCreator#createProxy(..)
方法中有提到过;目标类没有实现接口;
- 获取目标类
- 如果目标类是一个接口或者是
java.lang.reflect.Proxy
的子类,则还是使用JDK 动态代理,创建一个JdkDynamicAopProxy
对象 - 否则,使用 CGLIB 动态代理,创建一个
ObjenesisCglibAopProxy
对象
-
否则,使用JDK 动态代理,创建一个
JdkDynamicAopProxy
对象
我们可以看到JDK 动态代理对应 JdkDynamicAopProxy
对象,CGLIB 动态代理对应 ObjenesisCglibAopProxy
(继承 CglibAopProxy
)对象,在创建这两个对象的时候都传入了一个参数,就是 AdvisedSupport
配置管理器对象。
回到前面的 ProxyFactory#createAopProxy()
方法中,这个 AdvisedSupport
对象就是这个 ProxyFactory
对象,它继承了 AdvisedSupport
。
再回到 AbstractAutoProxyCreator#createProxy(..)
方法中,这个 ProxyFactory
对象是在这创建的,包含了 TargetSource
目标类来源和能够应用于当前目标对象的所有 Advisor
。
所以,我们得到的JdkDynamicAopProxy
或者ObjenesisCglibAopProxy
都包含了创建 AOP 代理对象的所有配置信息,可以创建代理对象了。
通过上面的这个方法,我们还可以得出一个结论,关于
proxy-target-class
配置的含义是什么?首先这个配置表示是否进行类代理,也就是 CGLIB 动态代理,默认是
false
当为
false
时,优先使用 JDK 动态代理,如果目标类没有实现可代理的接口,那么还是使用 CGLIB 动态代理如果为
true
,优先使用 CGLIB 动态代理,如果目标类本身是一个接口,那么还是使用 JDK 动态代理
到这里,我们知道了使用哪种方式创建代理对象,那么接下里我们一起来看看两种方式创建代理对象的过程。
4. JdkDynamicAopProxy
org.springframework.aop.framework.JdkDynamicAopProxy
,JDK 动态代理类,实现了 InvocationHandler 接口,可创建代理对象
构造函数
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
/** use serialVersionUID from Spring 1.2 for interoperability. */
private static final long serialVersionUID = 5531744639992436476L;
/** We use a static Log to avoid serialization issues. */
private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
/** 代理对象的配置信息,例如保存了 TargetSource 目标类来源、能够应用于目标类的所有 Advisor */
private final AdvisedSupport advised;
/** 目标对象是否重写了 equals 方法 */
private boolean equalsDefined;
/** 目标对象是否重写了 hashCode 方法 */
private boolean hashCodeDefined;
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 // 没有 Advisor,表示没有任何动作
&& config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) // 没有来源
{
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
}
}
4.1 getProxy 方法
getProxy()
方法,获取一个 JDK 动态代理对象,如下:
@Override
public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); }
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
// <1> 获取需要代理的接口(目标类实现的接口,会加上 Spring 内部的几个接口,例如 SpringProxy)
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// <2> 判断目标类是否重写了 `equals` 或者 `hashCode` 方法
// 没有重写在拦截到这两个方法的时候,会调用当前类的实现
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// <3> 调用 JDK 的 Proxy#newProxyInstance(..) 方法创建代理对象
// 传入的参数就是当前 ClassLoader 类加载器、需要代理的接口、InvocationHandler 实现类
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
获取代理对象的过程如下:
-
获取需要代理的接口(目标类实现的接口,会加上 Spring 内部的几个接口,例如 SpringProxy)
-
判断目标类是否重写了
equals
或者hashCode
方法,没有重写在拦截到这两个方法的时候,会调用当前类的实现private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) { for (Class<?> proxiedInterface : proxiedInterfaces) { Method[] methods = proxiedInterface.getDeclaredMethods(); for (Method method : methods) { if (AopUtils.isEqualsMethod(method)) { this.equalsDefined = true; } if (AopUtils.isHashCodeMethod(method)) { this.hashCodeDefined = true; } if (this.equalsDefined && this.hashCodeDefined) { return; } } } }
-
调用 JDK 的
Proxy#newProxyInstance(..)
方法创建代理对象,入参的 InvocationHandler 实现了就是当前对象
对于上面 JDK 创建代理对象的过程是不是很熟悉,不清楚的小伙伴可以查看我前面 《初识 JDK、CGLIB 两种动态代理》 这篇文章
AopProxyUtils
org.springframework.aop.framework.AopProxyUtils
工具类,获取 JDK 创建代理对象时需要实现哪些接口,如下:
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
// <1> 获取需要代理的接口(目标类实现的接口),放入 `specifiedInterfaces` 中
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)) {
advised.setInterfaces(targetClass.getInterfaces());
}
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
// <2> 判断目标类实现的接口是否存在 SpringProxy|Advised|DecoratingProxy 接口,不存在需要添加一个
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
int nonUserIfcCount = 0;
if (addSpringProxy) {
nonUserIfcCount++;
}
if (addAdvised) {
nonUserIfcCount++;
}
if (addDecoratingProxy) {
nonUserIfcCount++;
}
Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
int index = specifiedInterfaces.length;
// <3> 如果目标类实现的接口没有 SpringProxy,则添加一个
// 这样创建的代理对象就会实现这个接口,就能知道这个代理对象是否由 Spring 创建
if (addSpringProxy) {
proxiedInterfaces[index] = SpringProxy.class;
index++;
}
// 添加一个 Advised 接口
if (addAdvised) {
proxiedInterfaces[index] = Advised.class;
index++;
}
// 添加一个 DecoratingProxy 接口
if (addDecoratingProxy) {
proxiedInterfaces[index] = DecoratingProxy.class;
}
// <4> 返回需要代理的接口
return proxiedInterfaces;
}
该方法的处理过程如下:
- 获取需要代理的接口(目标类实现的接口),放入
specifiedInterfaces
中 - 判断目标类实现的接口是否存在 SpringProxy|Advised|DecoratingProxy 接口,不存在需要添加一个
- 通常情况下,上面三个接口都会添加到
specifiedInterfaces
的后面 - 返回
specifiedInterfaces
数组
通过上面这个方法得到的结论:在 Spring 内部通过 JDK 创建的代理对象会实现额外的接口,包括 SpringProxy 标记接口,可区分代理对象是否为 Spring 创建的
4 CglibAopProxy
org.springframework.aop.framework.CglibAopProxy
,CGLIB 动态代理类,可创建代理对象
CGLIB 动态代理比 JDK 动态代理可要复杂得多~
构造函数
class CglibAopProxy implements AopProxy, Serializable {
// Constants for CGLIB callback array indices
// 因为 CGLIB 设置的 Callback 是一个数组,下面定义了数组中固定几个拦截器的位置
// 进行 AOP 代理的通用拦截器
private static final int AOP_PROXY = 0;
// 执行目标方法的拦截器
private static final int INVOKE_TARGET = 1;
// 空的 Callback 对象,对于 finalize() 方法,不需要进行任何处理
private static final int NO_OVERRIDE = 2;
// 目标对象调度器,用于获取目标对象
private static final int DISPATCH_TARGET = 3;
// 配置管理器的调度器,会返回一个 AdvisedSupport 对象
private static final int DISPATCH_ADVISED = 4;
// 处理 `equals(Object)` 方法的拦截器
private static final int INVOKE_EQUALS = 5;
// 处理 `hashCode()` 方法的拦截器
private static final int INVOKE_HASHCODE = 6;
/** Logger available to subclasses; static to optimize serialization. */
protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);
/** Keeps track of the Classes that we have validated for final methods. */
private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<>();
/** 代理对象的配置信息,例如保存了 TargetSource 目标类来源、能够应用于目标类的所有 Advisor */
protected final AdvisedSupport advised;
/** 创建代理对象的构造方法入参 */
@Nullable
protected Object[] constructorArgs;
/** 创建代理对象的构造方法的入参类型 */
@Nullable
protected Class<?>[] constructorArgTypes;
/** Dispatcher used for methods on Advised. 配置管理器的调度器,会返回一个 AdvisedSupport 对象 */
private final transient AdvisedDispatcher advisedDispatcher;
/**
* 缓存方法的调用器数组索引
* key:方法名称
* value:方法对应的方法调用器在 Callback 数组中的位置
*/
private transient Map<String, Integer> fixedInterceptorMap = Collections.emptyMap();
// 方法调用器在 Callback 数组中的偏移量
private transient int fixedInterceptorOffset;
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 // 没有 Advisor,表示没有任何动作
&& config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) // 没有来源
{
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
}
上面的每一个属性都有注释,都非常重要,在 Spring 的 CGLIB 动态代理创建代理对象时,会设置一个 Callback 数组,上面定义了数组中固定几个拦截器的位置
数组中前面的几个 Callback 如下:
0
:进行 AOP 代理的通用拦截器【重点关注】1
:执行目标方法的拦截器2
:空的 Callback 对象,例如finalize()
方法,不需要进行任何处理3
:目标对象调度器,用于获取目标对象4
:配置管理器的调度器,会返回一个 AdvisedSupport 对象5
:处理equals(Object)
方法的拦截器6
:处理hashCode()
方法的拦截器
4.1 getProxy 方法
getProxy()
方法,获取一个 CGLIB 动态代理对象,如下:
@Override
public Object getProxy() { return getProxy(null); }
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
try {
// <1> 获取目标类
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
// <2> 将目标类作为被代理的类
Class<?> proxySuperClass = rootClass;
// <3> 如果目标类已经被 CGLIB 提升(名称包含 `$$` 符号)
if (ClassUtils.isCglibProxyClass(rootClass)) {
// <3.1> 获取目标类的父类作为被代理的类
proxySuperClass = rootClass.getSuperclass();
// <3.2> 获取目标类实现的接口,并添加至当前 AdvisedSupport 配置管理器中
// 例如 `@Configuration` 注解的 Bean 会被 CGLIB 提升,实现了 EnhancedConfiguration 接口
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
// <4> 进行校验,仅打印日志,例如 final 修饰的方法不能被 CGLIB 提升
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
// <5> 创建 CGLIB 的增强类,并进行接下来的配置
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
// `useCache` 默认为 `true`,可通过 `cglib.useCache` 系统参数指定
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// <5.1> 设置被代理的类
enhancer.setSuperclass(proxySuperClass);
// <5.2> 设置需要代理的接口(可能没有,不过都会加上 Spring 内部的几个接口,例如 SpringProxy)
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
// <5.3> 设置命名策略,默认生成的代理对象的名称中包含 '$$' 和 'BySpringCGLIB'
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
// <5.4> 获取回调接口,也就是 MethodInterceptor 方法拦截器
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
// <5.5> 设置 Callback 过滤器,用于筛选出方法对应的 Callback 回调接口
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
// <6> 创建代理对象,CGLIG 字节码替身,创建目标类的子类
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
// 抛出 AopConfigException 异常
}
catch (Throwable ex) {
// 抛出 AopConfigException 异常
}
}
该方法的处理过程如下:
- 获取目标类
rootClass
- 将目标类作为被代理的类
proxySuperClass
- 如果目标类已经被 CGLIB 提升(名称包含
$$
符号)- 获取目标类的父类作为被代理的类
- 获取目标类实现的接口,并添加至当前 AdvisedSupport 配置管理器中,例如
@Configuration
注解的 Bean 会被 CGLIB 提升,实现了 EnhancedConfiguration 接口
- 进行校验,仅打印日志,例如 final 修饰的方法不能被 CGLIB 提升
- 创建 CGLIB 的增强类 Enhancer 对象,并进行接下来的配置
- 设置被代理的类为
proxySuperClass
- 设置需要代理的接口(例如 SpringProxy),在前面讲述 JDK 动态代理创建代理对象时已经讲过 AopProxyUtils 这个工具类,不同的是 CGLIB 不会添加 DecoratingProxy 这个接口
- 设置命名策略,默认生成的代理对象的名称中包含
$$
和BySpringCGLIB
- 调用
getCallbacks(Class<?>)
方法,获取回调数组Callback[] callbacks
,也就是 MethodInterceptor 方法拦截器 - 设置 Callback 过滤器为
ProxyCallbackFilter
,用于筛选出方法使用callbacks
中的哪个 Callback
- 设置被代理的类为
- 调用
createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks)
方法,创建代理对象,并返回
CGLIB 创建代理对象的过程整体上并不复杂,其中第 5.4
、5.5
和 6
步我们接下来逐步分析
4.2 getCallbacks 方法
getCallbacks(Class<?> rootClass)
方法,获取代理对象的 Callback 回调数组,如下:
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
// <1> 获取代理对象的三个配置信息
// `exposeProxy` 是否暴露代理对象,通常为 `false`
boolean exposeProxy = this.advised.isExposeProxy();
// `isFrozen` 配置管理器是否被冻结,通常为 `false`
boolean isFrozen = this.advised.isFrozen();
// `isStatic` 是否是静态的目标对象,也就是说目标对象是否每次都需要创建,通常为 `true`
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
// <2> 【重点】创建目标对象的拦截器,MethodInterceptor 方法拦截器,会对目标对象的方法进行拦截处理,之前筛选出来的 Advisor 会在这个里面被调用
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
// <3> 创建目标对象的执行器,用于执行目标方法
Callback targetInterceptor;
// <3.1> 如果需要暴露当前代理对象,则通过 AopContext 进行暴露,放入 ThreadLocal 中,其他的和下面都相同
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
// <3.2> 否则,不暴露
else {
targetInterceptor = (isStatic ?
// <3.2.1> 用于执行方法代理对象,并对最终的返回结果进一步处理(返回结果是否需要为代理对象,返回结果是否不能为空)
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
// <3.2.2> 和上者的区别就是,每次拦截都会重新获取目标对象,结束后释放该目标对象
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
// <4> 目标对象调度器,用于获取目标对象
Callback targetDispatcher = (isStatic ?
// <4.1> 目标对象的调度器,用于获取当前目标对象
new StaticDispatcher(this.advised.getTargetSource().getTarget()) :
// <4.2> 目标对象的调度器,空的 Callback,不做任何处理
new SerializableNoOp());
// <5> 生成主要的几个回调接口,也就是上面创建的几个 Callback,放入 `mainCallbacks` 数组
Callback[] mainCallbacks = new Callback[] {
// 0:进行 AOP 代理的通用拦截器
aopInterceptor, // for normal advice
// 1:执行目标方法的拦截器
targetInterceptor, // invoke target without considering advice, if optimized
// 2:空的 Callback 对象,例如 `finalize()` 方法,不需要进行任何处理
new SerializableNoOp(), // no override for methods mapped to this
// 3:目标对象调度器,用于获取目标对象
targetDispatcher,
// 4:配置管理器的调度器,会返回一个 AdvisedSupport 对象
// 因为代理对象会实现 Advised 接口,拦截到其里面的方法时,需要调用当前 AdvisedSupport 的方法
this.advisedDispatcher,
// 5:处理 `equals(Object)` 方法的拦截器
new EqualsInterceptor(this.advised),
// 6:处理 `hashCode()` 方法的拦截器
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
/*
* <6> 如果目标对象不需要每次都创建,且当前 AdvisedSupport 配置管理器被冻结了,性能优化,可暂时忽略
* 那么在创建代理对象的时候,就可以先将目标对象的每个方法对应的方法调用器解析出来,该过程有点性能损耗,这样在代理对象执行方法的时候性能有所提升
* 不过由于这里会解析出许多方法调用器,会占有一定的内存,以空间换时间
*/
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
/*
* <6.1> 遍历目标对象所有的方法
*/
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
// <6.1.1> 获取能够应用于该方法的所有拦截器(有序)
// 不同的 AspectJ 根据 @Order 排序
// 同一个 AspectJ 中的 Advice 排序:AspectJAfterThrowingAdvice > AfterReturningAdviceInterceptor > AspectJAfterAdvice > AspectJAroundAdvice > MethodBeforeAdviceInterceptor
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
// <6.1.2> 创建一个方法调用器
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
// <6.1.3> 将每个方法的对应的调用器的位置索引缓存起来
this.fixedInterceptorMap.put(methods.toString(), x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
// <6.2> 将 `mainCallbacks` 复制到 `callbacks` 数组
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
// <6.3> 将 `fixedCallbacks` 复制到 `callbacks` 数组(拼接在后面)
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
// <6.4> 记录一个已生成的方法调用器的偏移量
this.fixedInterceptorOffset = mainCallbacks.length;
}
// <7> 否则,不进行解析,取上面的几个主要的 Callback
else {
callbacks = mainCallbacks;
}
// <8> 返回这个目标对象对应的 Callback 数组
return callbacks;
}
该方法的处理过程如下:
-
是获取代理对象的三个配置信息
exposeProxy
是否暴露代理对象,通常为false
isFrozen
配置管理器是否被冻结,通常为false
isStatic
是否是静态的目标对象,也就是说目标对象是否每次都需要创建,通常为true
-
【重点】创建目标对象的拦截器,DynamicAdvisedInterceptor 方法拦截器,会对目标对象的方法进行拦截处理,代理对象的处理逻辑都在这里面完成
-
创建目标对象的执行器,用于执行目标方法
- 如果需要暴露当前代理对象,则通过 AopContext 进行暴露,放入 ThreadLocal 中,其他的和下面都相同
- 否则,不暴露
isStatic
为 true,创建 StaticUnadvisedInterceptor 对象,用于执行方法代理对象,并对最终的返回结果进一步处理(返回结果是否需要为代理对象,返回结果是否不能为空)- 否则,创建 DynamicUnadvisedInterceptor 对象,和上者的区别就是,每次拦截都会重新获取目标对象,结束后释放该目标对象
-
目标对象调度器,用于获取目标对象
isStatic
为 true,创建 StaticDispatcher 对象,目标对象的调度器,用于获取当前目标对象- 否则,创建 SerializableNoOp 对象,空的 Callback,不做任何处理
-
生成主要的几个回调接口,也就是上面创建的几个 Callback,放入
mainCallbacks
数组,可以回到上面的构造函数看看哦😈0
:进行 AOP 代理的通用拦截器1
:执行目标方法的拦截器2
:空的 Callback 对象,例如finalize()
方法,不需要进行任何处理3
:目标对象调度器,用于获取目标对象4
:配置管理器的调度器,会返回一个 AdvisedSupport 对象,因为代理对象会实现 Advised 接口,拦截到其里面的方法时,需要调用当前 AdvisedSupport 的方法5
:处理equals(Object)
方法的拦截器6
:处理hashCode()
方法的拦截器 -
如果目标对象不需要每次都创建,且当前 AdvisedSupport 配置管理器被冻结了(默认不会),这一步做了一个性能优化,具体查看上面的代码
在创建代理对象的时候,就可以先将目标对象的每个方法对应的方法调用器解析出来,该过程有点性能损耗,这样在代理对象执行方法的时候性能有所提升;不过由于这里会解析出许多方法调用器,会占有一定的内存,以空间换时间
-
否则,不进行解析,取上面
mainCallbacks
-
返回这个目标对象对应的 Callback 数组
获取代理对象的 Callback 过程稍微有点复杂,因为代理对象处理不同的方法使用到的 Callback 也是不同的。不过你要知道的是上面第 2
步,第一个 Callback 就是 DynamicAdvisedInterceptor 对象,该对象用于进行 AOP 代理的通用拦截器,目标类的方法在这个拦截器中进行处理。这个对象和 JDK 动态代理创建的代理对象的实现差不多,所以都放入下一篇文章进行分析😈
4.3 ProxyCallbackFilter
CglibAopProxy 的私有内部静态类,用于筛选方法出对应的 Callback 对象
private static class ProxyCallbackFilter implements CallbackFilter {
private final AdvisedSupport advised;
private final Map<String, Integer> fixedInterceptorMap;
private final int fixedInterceptorOffset;
public ProxyCallbackFilter(
AdvisedSupport advised, Map<String, Integer> fixedInterceptorMap, int fixedInterceptorOffset) {
this.advised = advised;
this.fixedInterceptorMap = fixedInterceptorMap;
this.fixedInterceptorOffset = fixedInterceptorOffset;
}
/**
* 根据 Method 返回我们需要的 Callback 在数组中的位置
*/
@Override
public int accept(Method method) {
// <1> 如果该方法是 `finalize()`
if (AopUtils.isFinalizeMethod(method)) {
// 返回一个空 Callback 对象,不对该方法做任何处理
return NO_OVERRIDE;
}
// <2> 如果该方法是 Advised 中的方法,也就是需要 AdvisedSupport 来执行
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 返回一个配置管理器的调度器,会返回一个 AdvisedSupport 对象去执行这个方法
return DISPATCH_ADVISED;
}
// We must always proxy equals, to direct calls to this.
// <3> 如果该方法是 `equals(Object)` 方法
if (AopUtils.isEqualsMethod(method)) {
// 返回处理 `equals(Object)` 方法的拦截器去执行该方法
return INVOKE_EQUALS;
}
// We must always calculate hashCode based on the proxy.
// <4> 如果该方法是 `hashCode()` 方法
if (AopUtils.isHashCodeMethod(method)) {
// 返回处理 `hashCode()` 方法的拦截器去执行该方法
return INVOKE_HASHCODE;
}
// <5> 获取目标类 Class 对象
Class<?> targetClass = this.advised.getTargetClass();
// Proxy is not yet available, but that shouldn't matter.
// <6> 获取能够应用于该方法的所有拦截器,仅判断是否存在 Advice
List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
boolean haveAdvice = !chain.isEmpty();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
boolean isFrozen = this.advised.isFrozen();
// <7> 如果有 Advice 或者配置没有被冻结,通常情况都会进入这里
if (haveAdvice || !isFrozen) {
// If exposing the proxy, then AOP_PROXY must be used.
// <7.1> 如果需要暴露这个代理对象,默认为 `false`
if (exposeProxy) {
// 返回处理 AOP 代理的通用拦截器去执行该方法
return AOP_PROXY;
}
String key = method.toString();
// Check to see if we have fixed interceptor to serve this method.
// Else use the AOP_PROXY.
// <7.2> 如果目标对象是单例的,且配置被冻结,且存在对应的方法调用器
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
// We know that we are optimizing so we can use the FixedStaticChainInterceptors.
// 返回已经存在的方法调用器
int index = this.fixedInterceptorMap.get(key);
return (index + this.fixedInterceptorOffset);
}
// <7.3> 否则(通常会走到这一步)
else {
// 返回处理 AOP 代理的通用拦截器去执行该方法
return AOP_PROXY;
}
}
// <8> 否则
else {
// <8.1> 如果需要暴露代理对象,或者不是单例模式,默认这两种情况都不满足
if (exposeProxy || !isStatic) {
// 则返回执行目标方法的拦截器
return INVOKE_TARGET;
}
Class<?> returnType = method.getReturnType();
// <8.2> 如果该方法需要返回的就是目标类,暂时不清楚这种情况
if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
// 那么返回执行目标方法的拦截器,返回当前对象
return INVOKE_TARGET;
}
// <8.3> 否则,返回目标对象调度器,用于获取目标对象,让目标对象自己去执行这个方法
else {
return DISPATCH_TARGET;
}
}
}
}
我们直接看到实现的 accept(Method method)
方法的处理逻辑:
- 如果该方法是
finalize()
,返回一个空 Callback 对象,不对该方法做任何处理 - 如果该方法是 Advised 中的方法,也就是需要 AdvisedSupport 来执行,返回一个配置管理器的调度器,会返回一个 AdvisedSupport 对象去执行这个方法
- 如果该方法是
equals(Object)
方法,返回处理equals(Object)
方法的拦截器去执行该方法 - 如果该方法是
hashCode()
方法,返回处理hashCode()
方法的拦截器去执行该方法 - 获取目标类 Class 对象
- 获取能够应用于该方法的所有拦截器,仅判断是否存在 Advice
- 如果有 Advice 或者配置没有被冻结,通常情况都会进入这里
- 如果需要暴露这个代理对象,默认为
false
,返回处理 AOP 代理的通用拦截器去执行该方法 - 如果目标对象是单例的,且配置被冻结,且存在对应的方法调用器,返回已经存在的方法调用器
- 否则(通常会走到这一步),返回进行 AOP 代理的通用拦截器去执行该方法
- 如果需要暴露这个代理对象,默认为
- 否则
- 如果需要暴露代理对象,或者不是单例模式,默认这两种情况都不满足,返回执行目标方法的拦截器
- 如果该方法需要返回的就是目标类,暂时不清楚这种情况,那么返回执行目标方法的拦截器,返回当前对象
- 否则,返回目标对象调度器,用于获取目标对象,让目标对象自己去执行这个方法
上面的处理过程基本上都根据 Method 进行判断,然后返回一个 int
数值,这个值代表去取 Callback 数组中的那个 Callback,回看上面讲到的几个方法你就全部理解了。
我们来看到上面的第 7.3
步,返回的是一个 0
,表示使用第一个 Callback 进行处理,对应的就是 DynamicAdvisedInterceptor 对象,这个对象和 JDK 动态代理创建的代理对象的实现差不多,所以都放入下一篇文章进行分析😈
4.4 createProxyClassAndInstance 方法
createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks)
方法,创建代理对象,如下:
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
// 设置使用构造器期间不进行拦截
enhancer.setInterceptDuringConstruction(false);
// 设置 Callback 数组
enhancer.setCallbacks(callbacks);
// 创建一个代理对象(目标类的子类)
return (this.constructorArgs != null && this.constructorArgTypes != null ?
// 使用指定的构造方法
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
// 使用默认的构造方法
enhancer.create());
}
这个方法在 ObjenesisCglibAopProxy 子类中被重写了,Spring 内部也是使用 ObjenesisCglibAopProxy 这个类,因为 CGLIB 创建的子类考虑到通过构造器实例化代理对象,可能会存在构造器不合适的情况,所以 Spring 采用 Objenesis 实例化对象,不通过构造器创建实例对象
4.4 ObjenesisCglibAopProxy
org.springframework.aop.framework.ObjenesisCglibAopProxy
,继承 CglibAopProxy 类,重写 createProxyClassAndInstance(..)
方法
class ObjenesisCglibAopProxy extends CglibAopProxy {
/**
* 创建一个 Objenesis 对象
* [**Objenesis**](http://objenesis.org/) 是一个小型 Java 库,目的是为一些特殊的 Class 对象实例化一个对象
* 应用场景:
* 1. 序列化,远程调用和持久化 - 对象需要实例化并存储为到一个特殊的状态,而没有调用代码
* 2. 代理,AOP 库和 Mock 对象 - 类可以被子类继承而子类不用担心父类的构造器
* 3. 容器框架 - 对象可以以非标准的方式被动态实例化
*/
private static final SpringObjenesis objenesis = new SpringObjenesis();
public ObjenesisCglibAopProxy(AdvisedSupport config) {
super(config);
}
@Override
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
// <1> 先创建代理对象的 Class 对象(目标类的子类)
Class<?> proxyClass = enhancer.createClass();
Object proxyInstance = null;
// <2> 是否使用 Objenesis 来实例化代理对象,默认会
// 可通过 在 `spring.properties` 文件中添加 `spring.objenesis.ignore=false` 来禁止
if (objenesis.isWorthTrying()) {
try {
// <2.1> 通过 Objenesis 实例化代理对象(非标准方式,不使用构造方法进行实例化)
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
}
catch (Throwable ex) {
logger.debug("Unable to instantiate proxy using Objenesis, " +
"falling back to regular proxy construction", ex);
}
}
// <3> 如果借助 Objenesis 实例化代理对象失败
if (proxyInstance == null) {
// Regular instantiation via default constructor...
try {
// <3.1> 选择构造器,指定了参数则使用对应的构造器,否则使用默认构造器
Constructor<?> ctor = (this.constructorArgs != null ?
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
proxyClass.getDeclaredConstructor());
ReflectionUtils.makeAccessible(ctor);
// <3.2> 通过构造器实例化代理对象(反射)
proxyInstance = (this.constructorArgs != null ?
ctor.newInstance(this.constructorArgs) : ctor.newInstance());
}
catch (Throwable ex) {
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
"and regular proxy instantiation via default constructor fails as well", ex);
}
}
// <4> 设置 Callback 数组
((Factory) proxyInstance).setCallbacks(callbacks);
// <5> 返回代理对象
return proxyInstance;
}
}
首先我们来看到 SpringObjenesis 这个对象,它实现了 Objenesis 接口,Objenesis 是一个小型 Java 库,目的是为一些特殊的 Class 对象实例化一个对象,应用场景:
- 序列化,远程调用和持久化 - 对象需要实例化并存储为到一个特殊的状态,而没有调用代码
- 代理,AOP 库和 Mock 对象 - 类可以被子类继承而子类不用担心父类的构造器
- 容器框架 - 对象可以以非标准的方式被动态实例化
创建代理对象的过程如下:
- 先通过 Enhancer 创建代理对象的 Class 对象(目标类的子类)
- 是否使用 Objenesis 来实例化代理对象,默认会
- 通过 Objenesis 实例化代理对象(非标准方式,不使用构造方法进行实例化)
- 如果借助 Objenesis 实例化代理对象失败
- 选择构造器,指定了参数则使用对应的构造器,否则使用默认构造器
- 通过构造器实例化代理对象(反射)
- 设置 Callback 数组
- 返回代理对象
总结
在前面的《Spring AOP 自动代理(一)入口》文章中,分析了 Spring AOP 自动代理的入口是 AbstractAutoProxyCreator 对象,其中自动代理的过程主要分为下面两步:
- 筛选出能够应用于当前 Bean 的 Advisor
- 找到了合适 Advisor 则创建一个代理对象, JDK 动态代理或者 CGLIB 动态代理
上一篇《Spring AOP 自动代理(二)筛选合适的通知器》文章分析了上面第 1
步的处理过程。本文是接着前面两篇文章分析上面第 2
个过程,Spring 是如何创建代理对象的,大致流程如下:
-
创建一个 ProxyFactory 代理工厂对象,设置需要创建的代理类的配置信息,例如 Advisor 数组和 TargetSource 目标类来源
-
借助 DefaultAopProxyFactory 选择 JdkDynamicAopProxy(JDK 动态代理)还是 ObjenesisCglibAopProxy(CGLIB 动态代理)
-
当
proxy-target-class
为false
时,优先使用 JDK 动态代理,如果目标类没有实现可代理的接口,那么还是使用 CGLIB 动态代理 -
如果为
true
,优先使用 CGLIB 动态代理,如果目标类本身是一个接口,那么还是使用 JDK 动态代理
-
-
通过 JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy 创建一个代理对象
- JdkDynamicAopProxy 本身是一个 InvocationHandler 实现类,通过 JDK 的
Proxy.newProxyInstance(..)
创建代理对象 - ObjenesisCglibAopProxy 借助 CGLIB 的 Enhancer 创建代理对象,会设置 Callback 数组和 CallbackFilter 筛选器(选择合适 Callback 处理对应的方法),整个过程相比于 JDK 动态代理更复杂点,主要的实现在 DynamicAdvisedInterceptor 方法拦截器中
- JdkDynamicAopProxy 本身是一个 InvocationHandler 实现类,通过 JDK 的
其中 CGLIB 实例化代理对象的过程使用到了 Objenesis,它是一个小型 Java 库,目的是为一些特殊的 Class 对象实例化一个对象。因为 CGLIB 创建的子类考虑到通过构造器实例化代理对象,可能会存在构造器不合适的情况,所以 Spring 采用 Objenesis 实例化对象,不通过构造器创建实例对象。
好了,本篇文章就到这里了,Spring AOP 中整个自动代理过程到这里也就结束了。对于 JDK 动态代理和 CGLIB 动态代理创建的代理对象,它们的具体实现(或者说是方法拦截处理)在这里并没有体现出来,前者的实现在 JdkDynamicAopProxy 中,因为它实现了 InvocationHandler 接口,后者的实现则在 DynamicAdvisedInterceptor 方法拦截器中,这些内容将在下篇文章进行分析。