创建目标类的代理对象过程
步骤1
finishBeanFactoryInitialization(beanFactory), 完成BeanFactory的初始化工作,就是来创建剩下的单实例bean,
在创建的过程中就会被各个后置处理器拦截掉,下面我们就看看finishBeanFactoryInitialization(beanFactory);

步骤2
进入到 finishBeanFactoryInitialization(beanFactory)中,就会看到来到 beanFactory.preInstantiateSingletons()创建bean

进入preInstantiateSingletons()方法中,看到在循环所有bean创建对象,通过getBean(beanName)创建

最后来到doGetBean(name, null, null, false)方法,首先检查单实例的缓存中是否存在当前对象

如果存在就直接返回,否则就通过调用 getSingleton()获得单实例bean,只要创建好的bean就会被缓存起来,保证单实例bean

之后调用createBean(beanName,mbd,args)创建bean

进入到createBean()后就会调用resolveBeforeInstantiation(beanName, mbdToUse)方法,
希望后置处理器再此能返回一个代理对象,如果能返回就是使用,否则就调用下面的doCreateBean()创建,对于doCreateBean()方法之前已经详细介绍过了,
就是先创建bean实例,然后为bean属性赋值,然后在调用bean的init方法前后调用后置处理器等等操作。

我们来到 resolveBeforeInstantiation(beanName, mbdToUse)中, 给目标对象一个创建一个代理的机会
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// 检查是否尚未确定不需要在实例化前解析
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 确保此时 bean 类已经被解析
// 如果不是合成 bean 且存在 InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 确定目标 bean 的类型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 应用实例化前的 BeanPostProcessor
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 如果成功创建了 bean,则应用初始化后的处理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 标记是否成功在实例化前解析了 bean
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
先调用 applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)方法,进入其中,看到

先循环所有后置处理器,判断是不是InstantiationAwareBeanPostProcessor类型的后置处理器,
如果是就调用它的postProcessBeforeInstantiation(beanClass, beanName)方法,
而我们之前已经说过AnnotationAwareAspectJAutoProxyCreator是SmartInstantiationAwareBeanPostProcessor类型的后置处理器,
而SmartInstantiationAwareBeanPostProcessor又继承了InstantiationAwareBeanPostProcessor
所以AnnotationAwareAspectJAutoProxyCreator也就是InstantiationAwareBeanPostProcessor这种类型的后置处理器,
最后就会调用AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation()方法,
我们就来看看postProcessBeforeInstantiation()方法都干了些啥?
步骤3
现在我们就关心我们自己创建的LogAspect和MathCal是怎样创建的?我们的MathCal来到
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(Class<?>, String)方法
(AnnotationAwareAspectJAutoProxyCreator中没有postProcessBeforeInstantiation()方法的实现,只能调用父类的方法),
首先判断是否在advisedBeans中,advisedBeans中保存了所有需要增强的目标对象bean。第一次创建是不会包含的,所有 if 没进去。

然后就来到第二个判断,首先判断当前bean是否是基础类型即判断是否是实现了Advice,Pointcut,Advisor,AopInfrastructureBean
这几个接口,其次还会判断是否是加了@Aspect注解的

最后再通过shouldSkip(beanClass, beanName)判断是否需要跳过
/**
* 判断是否应该跳过对指定 Bean 类和 Bean 名称的处理。
*
* @param beanClass Bean 的类对象
* @param beanName Bean 的名称
* @return 如果应该跳过处理则返回 true,否则返回 false
*/
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 待办事项:考虑通过缓存切面名称列表来进行优化
// 查找所有候选的 Advisor(通知器)
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 遍历所有候选的 Advisor
for (Advisor advisor : candidateAdvisors) {
// 检查当前 Advisor 是否为 AspectJ 切点通知器
if (advisor instanceof AspectJPointcutAdvisor) {
// 获取该 Advisor 中的通知,并将其转换为 AbstractAspectJAdvice 类型
// 然后获取切面的名称,并与当前 Bean 的名称进行比较
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
// 如果切面名称与 Bean 名称相等,则表示应该跳过对该 Bean 的处理
return true;
}
}
}
// 如果没有匹配到需要跳过的情况,则调用父类的 shouldSkip 方法进行判断
return super.shouldSkip(beanClass, beanName);
}

在shouldSkip()中首先获得四个增强器即切面中的四个通知方法,将通知方法包装为InstantiationModelAwarePointcutAdvisor类型的,
判断增强器是否是AspectJPointcutAdvisor类型的,而我们的类型不是,就会调用父类的super.shouldSkip(beanClass, beanName);
返回false,最后就返回null,继续 doCreateBean(beanName, mbdToUse, args)-->createBeanInstance(beanName, mbd, args)
-->populateBean(beanName, mbd, instanceWrapper)-->initializeBean(beanName, exposedObject, mbd)-->applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
之后又来到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(Object, String)方法

调用 wrapIfNecessary(bean, beanName, cacheKey) 进入其中
/**
* 如果有必要,对指定的 Bean 进行包装(创建代理)。
*
* @param bean 要检查并可能包装的 Bean 实例
* @param beanName Bean 的名称
* @param cacheKey 用于缓存的键,代表当前 Bean 的唯一标识
* @return 如果需要,返回包装后的代理对象;否则返回原始的 Bean 实例
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 检查 beanName 是否不为空,并且 targetSourcedBeans 集合中包含该 beanName
// 如果是,则表示该 Bean 已经由 TargetSource 处理过,不需要再进行包装,直接返回原始 Bean
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 从 advisedBeans 缓存中获取当前 Bean 对应的处理标记
// 如果标记为 false,表示该 Bean 不需要被代理,直接返回原始 Bean
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 检查该 Bean 的类是否为基础设施类(如 Spring 内部使用的类),或者是否应该跳过该 Bean 的处理
// 如果是,则将该 Bean 的处理标记为 false 并放入 advisedBeans 缓存中,然后返回原始 Bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果存在通知(Advice),则创建代理
// 获取该 Bean 对应的通知和通知器数组
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果获取到的通知和通知器数组不为 DO_NOT_PROXY(表示需要进行代理)
if (specificInterceptors != DO_NOT_PROXY) {
// 将该 Bean 的处理标记为 true 并放入 advisedBeans 缓存中
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 将代理对象的类型放入 proxyTypes 缓存中
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回代理对象
return proxy;
}
// 如果不需要进行代理,将该 Bean 的处理标记为 false 并放入 advisedBeans 缓存中
this.advisedBeans.put(cacheKey, Boolean.FALSE);
// 返回原始 Bean
return bean;
}
获取所有候选增强器,然后通过切点表达式进行筛选,获得与其当前匹配的bean增强器(通知方法),如何获取呢?


通过 createProxy() 创建代理对象,最后保存当前bean到 advisedBeans中,表示当前bean已经增强

先根据 Bean 名称获取其对应的增强器(通知方法),保存到proxyFactory中,通过proxyFactory.getProxy(getProxyClassLoader()),获得代理对象
/**
* 创建指定 Bean 的代理对象。
*
* @param beanClass Bean 的类对象,即要被代理的目标类
* @param beanName Bean 的名称,用于标识该 Bean
* @param specificInterceptors 该 Bean 对应的特定拦截器和通知器数组
* @param targetSource 目标对象的源,用于获取实际的目标对象
* @return 创建好的代理对象
*/
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
// 检查当前的 Bean 工厂是否为 ConfigurableListableBeanFactory 类型
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
// 如果是,则通过 AutoProxyUtils 工具类暴露目标类信息到 Bean 工厂中
// 这有助于在某些情况下让其他组件知道目标类的实际类型
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 创建一个 ProxyFactory 实例,用于创建代理对象
ProxyFactory proxyFactory = new ProxyFactory();
// 将当前对象的配置信息复制到 ProxyFactory 中
// 确保代理工厂使用相同的配置
proxyFactory.copyFrom(this);
// 检查 ProxyFactory 是否已经配置为代理目标类(使用 CGLIB 代理)
if (!proxyFactory.isProxyTargetClass()) {
// 如果没有配置为代理目标类,则检查是否应该代理目标类
if (shouldProxyTargetClass(beanClass, beanName)) {
// 如果应该代理目标类,则将 ProxyFactory 的配置设置为代理目标类
proxyFactory.setProxyTargetClass(true);
} else {
// 否则,评估目标类实现的接口,根据接口情况来配置代理方式
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 根据 Bean 名称获取其对应的增强器
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 将构建好的增强器添加到 ProxyFactory 中
proxyFactory.addAdvisors(advisors);
// 设置目标对象(被代理对象)
proxyFactory.setTargetSource(targetSource);
// 对 ProxyFactory 进行自定义配置,允许子类进行额外的定制
customizeProxyFactory(proxyFactory);
// 设置 ProxyFactory 是否冻结代理配置
// 如果冻结,则在创建代理后不能再修改代理的配置
proxyFactory.setFrozen(this.freezeProxy);
// 检查通知器是否已经预先过滤
if (advisorsPreFiltered()) {
// 如果已经预先过滤,则设置 ProxyFactory 为预过滤状态
proxyFactory.setPreFiltered(true);
}
// 使用 ProxyFactory 创建代理对象,并指定代理类加载器
return proxyFactory.getProxy(getProxyClassLoader());
}
进入其中
/**
* 根据提供的 AOP 配置信息创建 AOP 代理对象。
*
* @param config 包含 AOP 代理配置的 AdvisedSupport 对象
* @return 一个 AopProxy 实例,用于生成具体的 AOP 代理对象
* @throws AopConfigException 如果配置信息不符合代理创建要求,抛出此异常
*/
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 检查是否满足使用 CGLIB 代理的条件:
// 1. 是否开启了优化选项
// 2. 是否明确指定使用目标类代理
// 3. 是否没有用户提供的代理接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// 获取目标类的 Class 对象
Class<?> targetClass = config.getTargetClass();
// 如果目标类为 null,说明无法确定目标类,抛出 AopConfigException 异常
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果目标类是接口或者是代理类,使用 JDK 动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则,使用 ObjenesisCglibAopProxy(基于 CGLIB 的代理)
return new ObjenesisCglibAopProxy(config);
} else {
// 如果不满足使用 CGLIB 代理的条件,默认使用 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
}
spring自动决定使用JDK方式代理还是使用Cglib方式代理

至此就创建出代理对象啦,并返回回去了,以后容器中拿到的就是代理对象了,接下来拿到代理对象,如何调用增强方法

浙公网安备 33010602011771号