AbstractAutoProxyCreator创建AOP代理
Spring 通过 AbstractAutoProxyCreator
来创建 AOP 代理,AbstractAutoProxyCreator 是一个抽象类,它实现了 BeanPostProcessor
接口,用于在 bean 初始化完成之后创建它的代理
AbstractAutoProxyCreator
的类继承结构如下图所示(这里忽略了 Aware 相关的接口,不影响后续理解):
考虑普通的创建代理的流程,我们只需要关注 BeanPostProcessor
接口。回顾下 BeanPostProcessor
接口,它可以用于在 bean 的初始化前后对 bean 进行处理,可参考下图理解
若要创建 bean 的代理,可通过 BeanPostProcessor
的 postProcessAfterInitialization
回调方法来实现。在调用 postProcessAfterInitialization
方法时,bean 已经完成了实例化、属性填充、初始化等操作,是一个可直接使用的实例。
1 | public Object postProcessAfterInitialization( Object bean, String beanName){ |
在解决循环依赖时,还会触发提前创建代理。下面先看下提前创建代理的情况
提前创建代理
所谓提前创建代理,是指的下面这种情况:
为了解决循环依赖问题,在 populateBean 之前,如果允许提前暴露,spring 会将实例化好的 bean 放入 singletonFactory 中。
1 | boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && |
循环依赖最终解决时会通过 singletonFactory 获取依赖的 bean,进而触发到 getEarlyBeanReference
方法的调用。
1 | // 通过工厂创建实例 |
此时也应该返回代理后的实例,这也就需要提前创建代理。要在此创建代理,AbstractAutoProxyCreator
需要实现 SmartInstantiationAwareBeanPostProcessor
的 getEarlyBeanReference
方法。
1 | protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { |
getEarlyBeanReference
方法的实现如下
1 | public Object getEarlyBeanReference(Object bean, String beanName) { |
wrapIfNecessary
方法是一个公用的创建代理方法,这个在后面再具体看
正常流程创建代理
如果没有提前创建代理,则走正常的流程,在 postProcessAfterInitialization
方法中处理。此时 if (!this.earlyProxyReferences.contains(cacheKey))
判断通过,会走 wrapIfNecessary(bean, beanName, cacheKey)
创建代理。
1 | public Object postProcessAfterInitialization( Object bean, String beanName){ |
下面主要看下 wrapIfNecessary
方法的实现。首先是一些不需要创建代理的情况判断
1 | if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { |
然后会走到创建代理流程。先获取 Advice 和 Advisor
1 | Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); |
具体的实现交给了子类,比如 BeanNameAutoProxyCreator 是根据 beanName 去匹配决定是否进行代理,它的实现如下:
1 | protected Object[] getAdvicesAndAdvisorsForBean( |
接下来是创建 AOP 代理
1 | Object proxy = createProxy( |
它的实现如下:
1 | protected Object createProxy(Class<?> beanClass, String beanName, |
getProxy 有两种实现:jdk 代理和 cglib 代理。它是通过 AopProxyFactory 来判断使用何种方式的。
1 | public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { |
若要使用 cglib 代理,目标类不能是接口,并且不能是 jdk 产生的的代理类,另外还需满足以下条件之一
optimize 设置为 true
1
2
3
4
5
6/**
* 代理是否应进行优化.
*/
public boolean isOptimize() {
return this.optimize;
}proxyTargetClass 设置为 true
1
2
3
4
5
6/**
* 是否直接代理目标类以及任何接口.
*/
public boolean isProxyTargetClass() {
return this.proxyTargetClass;
}代理的接口为空,或者仅包含 SpringProxy 接口
1
2
3
4private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
- 2020-04-06
InstantiationAwareBeanPostProcessor
是BeanPostProcessor
的子接口,新增了一个实例化之前(BeforeInstantiation)的回调、一个实例化之后(AfterInstantiation)填充 property 之前的回调 - 2020-03-31
当调用 BeanFactory.getBean 方法获取 Bean 时,如果 Bean 还未创建,则会触发 Bean 的创建,本文主要关注 Bean 的创建过程。
- 2020-04-03
Spring 中定义了一个 Aware 接口,用于表示一个 bean 可以通过回调的方式接收 Spring 容器的通知。该接口并未定义具体的方法,而是交给子类决定,通常只包含一个只接收单个入参并且返回结果为 void 的方法。
- 2020-04-18
在 dubbo的Reference注解实现原理 中提到,
@Reference
注解用于实现 RPC client 代理的自动注入,这是通过ReferenceAnnotationBeanPostProcessor
来实现的。若要让其生效,还需要在这之前将其注册到 BeanFactory 中。 - 2020-03-27
Bean 的创建与获取是一个比较复杂的过程,本文主要关注 bean 获取的过程。