概要
过度
我们前面介绍了对<aop:aspectj-autoproxy />
标签的解析过程,其实整体就做了一件事:创建一个后处理器并注册。
本文我们主要介绍这个后处理器的工作原理。当然我们关注的重点是AOP相关的处理逻辑。
内容简介
结合我们之前了解的BeanFactory
逻辑,了解此后处理器的工作逻辑。
对此后处理器创建AOP的逻辑进行详细分析,包括:
- 找出所有注册的增强器
- 针对要实例化的Bean选择合适增强器
- 利用选出的合适的增强器创建动态代理
所属环节
针对Bean生成动态代理
上下环节
上文:解析<aop:aspectj-autoproxy />
节点
下文:Spring构建的动态代理对象的工作原理
源码解析
入口
我们上面讲到解析标签最终会导致AnnotationAwareAspectJAutoProxyCreator
的注册,这个类的继承关系如下:
emmmm,又是一个继承关系超级复杂的类,我们不再像前面学习BeanFactory
时对每个类的角色、功能一一介绍了,我们把主要注意力集中在调用上面,这样能让我们思路清晰。
这里很容易发现AbstractAutoProxyCreator
继承了SmartInstantiationAwareBeanPostProcessor
。这里应该对BeanPostProcessor
的主要处理逻辑有实现。
在扩展中,我们对击中Bean的后处理器做了介绍。根据我们在扩展中的介绍,我们确认进行AOP动态代理创建的主要有三个地方:
postProcessBeforeInstantiation
getEarlyBeanReference
postProcessAfterInitialization
其中第一种情况涉及短路,第二、第三种不涉及。而第一种段路但是会继续手动调用postProcessAfterInitialization
。所以实际调用的搭配方案是:
- 1,3
- 2,3
我们依次介绍三个调用方法,最后再整合看。我们先介绍一下基本的数据结构,方便后续代码理解:
基础数据结构
// 这个里面存的是通过 TargetSourceCreator 创建的 Bean 实例,不走 Spring 的创建实例、填值、初始化、提前暴露啥的,直接
// 一步走到最后的调用初始化之后的后处理器
private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
// 这个是配合 BeanFactory 进行解决循环依赖时提供的
// key: 计算得到的 cacheKey
// value: 是完成创建实例后得到的地址。还没进行填值、初始化啥的
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
// 这个是将已经完成代理创建的对象进行缓存
// key: 计算得到的cacheKey
// value: 代理之后得到的 Class
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
// 已经增强的 Bean 的 map ,key 是根据 beanName 生成的。 value 是这个 bean 已经增强的原因:
// False 表示经过之前的判断,此 Bean 不需要增强。
// True 表示经过之前的判断,此 Bean 需要增强
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
四个属性。
前两个属性分别对应postProcessBeforeInstantiation
和getEarlyBeanReference
的实现。
后两个属性是做缓存以加快执行效率。
postProcessBeforeInstantiation
我们先上代码:
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
// TODO targetSourcedBeans 中没有针对这个 Bean 的缓存??????
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {//TODO 之前对此类 Bean 做过判断
return null;
}
// 1. AOP配置的基础类【不需进行AOP】
// 2. 子类自行定义一个判断条件,将自己不想进行代理的类摘出去
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.
// 这里看一下,我们是不是配置了对应的 TargetSourceCreator 来生成此类实例,如果配置了的话就直接走配置生成可用的目标实例
// 缓存创建的实例,然后在这里创建完成代理,不再走 Spring 的创建实例、属性填充、初始化啥的操作了
//
// 这里主要是提供给使用者一个短路 Spring 基础流程的机会,方便进行定制
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
// 存起来,表示下次处理 beanName ,直接走 TargetSourceCreator 并创建代理
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 得到我们配置的 Advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 根据我们配置的 Advisor 创建代理对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
// TODO 缓存一下我们创建的代理类【这里不清楚有啥用】
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;// 短路
}
return null;
}
protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
// We can't create fancy target sources for directly registered singletons.
if (this.customTargetSourceCreators != null &&
this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
TargetSource ts = tsc.getTargetSource(beanClass, beanName);
if (ts != null) {
// Found a matching TargetSource.
if (logger.isDebugEnabled()) {
logger.debug("TargetSourceCreator [" + tsc +
"] found custom TargetSource for bean with name '" + beanName + "'");
}
return ts;
}
}
}
// No custom TargetSource found.
return null;
}
思路如下:
上面的思路是有点乱的,你只需要明白一点就可以了,这个函数的职责是尝试借助TargetSourceCreator
完成实例构建,如果可以就可以短路操作,如果不行就走正常创建。这里面的一大堆判断也是在推断这个 Bean 是否之前做过这种判断,有没有保存好的判断结果。
有两个函数里封装了我们的核心操作:
getAdvicesAndAdvisorsForBean
createProxy
职责我们大概能猜到,具体的实现思路我们后面统一介绍。
getEarlyBeanReference
先上代码:
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean); // 这里的 Bean 是完成创建实例后得到的地址。还没进行填值、初始化啥的
return wrapIfNecessary(bean, beanName, cacheKey);
//TODO 这里提前进行了包装,如果是jdk动态代理,后面在注入时怎么玩????,看看代理之后会不会影响 getter/setter函数
}
这里思路很简单,因为实例已经存在了,所以我们做缓存,然后根据情况创建代理即可。其中wrapIfNecessary
方法后面详细介绍。
postProcessAfterInitialization
贴代码:
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
*
* @see #getAdvicesAndAdvisorsForBean
*/
// 如果要处理的 bean 实例被子类标识为需要代理的,就通过配置的拦截器创建代理
//
// 注意,这里的用词是拦截器,因为是通过回调完成的调用。过滤器 Filter 是和 servlet 容器切合到一起的,
// 是 tomcat 的东西
//
// 这里是将通过 Spring 创建实例、完成添值、初始化完成的对象实例或者前面postProcessBeforeInstantiation()短路
// 得到的完善的实例,在这里将需要进行代理的进行创建代理
//
// 注意,这里需要判断是否已经代理过,别在 postProcessBeforeInstantiation() 创建一次代理,这里再创建一次
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
// TODO 这里后面重新过一下 Spring 创建 Bean 实例的步骤,传进来的 beanName 是 alias 还是带 & 的还是单纯的 beanId
// TODO 如果不是单纯的 beanId ,这里可能会出错
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 这里意味着前面通过这个提前拿到的地址。在调用 postProcessAfterInitialization() 包裹时发现传进来的
// 已经和最开始的不一样了。那就重新根据情况看是否要创建代理
// TODO 这里能看出来和最开始暴露出去的不一样了,估计解决循环依赖是否成功只有依赖一下两种情况是否恰好发生:
// 1. 没有任何 Bean 引用了提前暴露出去的Bean
// 2. 在后面的 getEarlyBeanReference() 的处理过程中有操作继续包裹导致这里的不一致
// TODO 其实这里想多了,上面的都是建立在假设 earlyProxyReferences 就是暴露出去的对象,但是这里可以把它理解成一个记录是否提前创建代理的记录
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
思路很简单,还是委托给wrapIfNecessary
根据情况创建代理。只是之前可能做了提前暴露,用earlyProxyReferences
缓存协助判断看能否少走一步,加快构造速度。
动态代理创建内部逻辑记录
wrapIfNecessary
上面我们对三个后处理的钩子做了一些介绍,最后我们发现动态代理的创建基本委托给了wrapIfNecessary
,当然也有更细致的委托,这里我们从这里入手对动态代理介绍,根据我先撸过一次的经验来说,从这里入手会把上面依赖的函数都过一遍。
直接放代码:
// 如果这个 Bean 需要被代理,就代理一下
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// this.targetSourcedBeans.contains(beanName) 表示此 beanName 对应的 bean 没有走正经 Spring 创建实例的过程
// 直接搞定了。
// TODO 这种创建方式貌似不走AOP的东西
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 此 cacheKey 【通过 bean 实例得出】 之前做过判断,根据之前的判断是不用代理的
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 如果满足以下条件,则不对 bean 进行代理
// 1. 此类是基础类【配置代理相关的配置类】
// 2. 或者根据用户自定义的逻辑,不对它进行代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);// 这里做了缓存,方便有重复判断时加快速度
return bean;
}
// Create proxy if we have advice.
// 得到 bean 对应的增强方法,如果有需要增强的方法,则创建代理
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));
// TODO 看一下这个缓存是怎么做的??代理临时生成的类可以复用吗??
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 已经确定不用创建代理,缓存一下结果,方便后面的判断
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
思路如下:
我们主要介绍两个函数即可:
getAdvicesAndAdvisorsForBean
createProxy
正好是我们最开始的postProcessBeforeInstantiation
依赖的两个。
getAdvicesAndAdvisorsForBean
直接上代码:
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 继续委托
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
// 如果没查到就返回特定值,方便判断
// TODO 感觉这种设计方法还是不太好的,一个返回值有了多种解读语意,应该是 Spring 为了接口简洁做的一些妥协
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 获得所有的增强器
// 找出来,然后实例化
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 找到这个 bean 可以用的增强
// 这里涉及针对 aop 筛选类、方法的东西
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 这里留一个钩子,方便子类根据自己的需要进行增强器定制
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
还是老套路,继续向外委托,本函数只做基础的记录和转换。所以就一下子贴了两个函数上去。整体思路还是比较清楚的:
- 先拿到所有的增强器
- 根据Bean筛选出可用的增强器
- 返回
我们接下来依次看这两步的操作,先看第一步:拿到所有的增强器
// 返回 auto-proxy 中配置的所有的增强器
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
// 委托给专门负责增强器检索的类
return this.advisorRetrievalHelper.findAdvisorBeans();
}
我们看findAdvisorBeans
:
// 找到当前 BeanFactory 中所有的增强器
// TODO 注意,因为声明增强器的方法太多了,我们挑通用逻辑。
// 不支持 FactoryBean。。。。正常人打@Aspect注解也不会专门搞个 FactoryBean , 保持类的功能纯粹吧
// TODO 不支持正在实例化的bean。。。。这个再看
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
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!
// 得到实现了 Advisor 接口的所有 beanId
// 注意,这里传了 false ,不会对 FactoryBean 进行初始化后再比
// TODO 存疑,我们打的是 @Aspect 注解,什么时候转化成对应的 Advisor 类型的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)) {
// 等等,这个注意了,不是还没初始化的 Bean ,是正在初始化的。想一下,有没有什么问题?
// TODO 是不是为了避免循环依赖???毕竟这里是配置类,如果配置类依赖了马上要代理的单例(或者其他)类,解决循环依赖肯定是要失败的吧
// 所以,这里快刀斩乱麻,直接把这种危险依赖过滤掉了。鸡贼啊
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));
} catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
整体思路比较简单,就是找出了BeanFactory
中配置的所有的Advisor
,然后实例化返回。
接下来看第二步:根据Bean筛选出可用的增强器
// 检索增强器列表,找出所有可以用于 bean 代理的增强器
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
// 使用 ThreadLocal 保存此线程正在生成代理的目标 beanId ,应该是为了监控及防止死循环吧
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 老套路,处理完信息记录、条件验证之后,将要干的活委托给专门干这个活的人
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
// 清除之前存储的 beanId
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
我们继续深入看详细的实现思路:
// 从入参的增强器列表中筛出入参的class可用的
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) { // 没得选,就返回空
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
//IntroductionAdvisor 判断
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;
}
// 非 IntroductionAdvisor 判断是否可用
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
这里分了两种判断,很简单,因为Advisor
分两种:
-
IntroductionAdvisor
只判断到类级别 -
PointcutAdvisor
判断到方法级别
有兴趣可以深入去看,不过根据猜测,我们用到的应该都是第二种。
到这里,我们找出了所有可用的增强器。
createProxy
上面我们筛选出了合适的增强器,现在开始根据增强器构建动态代理。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
//这里应该是把代理处理之前的类进行保存
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory(); // 创建 ProxyFactory ,后面将用此对象通过传进去的信息决定 JDK/CGLIB 的选择
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) { // 只有在没有设置必须使用 CGLib 时才根据什么 BD字段、BD指定Class的接口进行判断
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
// 一个钩子,方便定制
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader()); // 代理的创建和获取
}
我们在这个函数主要根据Bean实例的情况和配置进行判断,并将判断的结果设置到proxyFactory
中,具体的创建操作委托给了proxyFactory
。
其实最关键的,这里做了一个判断,设置了两个属性:
- 判断了创建代理的方式:CGLib还是JDK。
- 设置了代理的目标实例,设置了动态代理的切面逻辑——增强器列表。
如果强制使用CGLib就直接使用,否则根据实例实现的接口判断能否使用JDK:
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
// 得到此类实现的所有接口
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
// 筛选一下接口,看有没有可以用来代理的,如果有就可以考虑 JDK 动态代理了。如果没有只能走 CGLIB
for (Class<?> ifc : targetInterfaces) {
// 1. 不能是那些 Spring 容器回调的接口
// 2. 不能是那些本地链接库的
// 3. 接口不能是空的
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
// 如果有符合条件的,就都存起来
// TODO 这里没有专门筛选那些,看看后面根据存的接口使用时有没有过滤
// TODO 感觉这里做的不是特别好
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 {
// 没有符合条件的接口,直接设置用 CGLIB 生成代理
proxyFactory.setProxyTargetClass(true);
}
}
这里整体的判断思路还是比较清晰的。
至此,我们就把配置都设置到proxyFactory
了,接下来我们看一下proxyFactory
创建动态代理的策略。
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
这里直接委托给了AopProxyFactory
,我们继续深入:
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 如果有特殊配置或者类的情况要求用 CGLIB
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
// 配置不合理,按照实际情况决定用 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config); // 否则根据配置用 CGLIB 动态代理
} else { // 默认用 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
}
思路很顺畅,至此我们根据配置和具体的信息得到了一个JdkDynamicAopProxy
或者一个ObjenesisCglibAopProxy
。
他们的工作原理下文会进行介绍。
扩展
Bean 后处理器相关介绍
BeanPostProcessor
提供了两个针对Bean的处理钩子,在调用初始化钩子前后进行调用。
postProcessBeforeInitialization
:
调用场景:Bean填充属性完成,在
initializeBean()
方法中先调用这个,再调用初始化的函数返回结果:返回加工结果,如果返回null,后面的
postProcessBeforeInitialization
就不再调用了【同时,此后处理器返回的也不再被使用】
postProcessAfterInitialization
:后处理器方法,可以在这里进行代理创建
调用场景:在
initializeBean()
方法中调用初始化的函数完成返回结果:返回加工结果,如果返回null,后面的
postProcessAfterInitialization
就不再调用了【同时,此后处理器返回的也不再被使用】
InstantiationAwareBeanPostProcessor
继承自上面的接口,新增两个后处理钩子用于在创建实例前后调用。
postProcessBeforeInstantiation
:后处理器方法, 可以在这里直接创建出实例并完成代理创建,这里会阻塞后面的几乎所有操作【创建实例/依赖注入/初始化】(阻塞我们介绍的那一大串的正常创建Bean的逻辑)
调用场景:在
createBean()
方法中调用,没有返回结果才委托给doCreateBean()
返回结果:返回加工结果,如果返回结果不是null,后面的流程被全部绕过,直接调用
postProcessAfterInitialization
,然后返回 Bean 实例
postProcessAfterInstantiation
:
调用场景:走正常的创建逻辑,在创建完实例之后、填值之前调用
返回结果:返回加工结果,如果返回结果是false,不再继续调用,且不再继续调用填值操作
postProcessPropertyValues
: 处理的主题不是 Bean 实例
调用场景:调用完上面的后处理器,找到合适的属性值之后调用这个方法对值进行处理
返回结果:返回加工结果,如果返回结果是null,不再使用此属性值进行属性填充
SmartInstantiationAwareBeanPostProcessor
继承自上买呢的接口,增加了用来预测创建 bean 的返回实例类型的方法。
predictBeanType
:预测 Bean 的Class,感觉不是很重要的地方
determineCandidateConstructors
:决定使用 bean 的构造函数,不再深入
getEarlyBeanReference
:获得 bean 的提前引用,用来解决循环引用,可以在这里进行代理创建。
调用场景:创建实例完成,是单例,需要先暴露实例以解决循环依赖再进行填值。调用此后处理器处理之后再暴露。
返回结果:返回加工结果,默认返回原对象。