Aop源码解析(二)核心对象创建

文章详细阐述了Spring在实例化带有AOP功能的Bean时,如何通过BeanPostProcessor和InstantiationAwareBeanPostProcessor接口,以及AbstractAutoProxyCreator子类AspectJAwareAdvisorAutoProxyCreator来处理Bean的创建。过程中涉及到构造方法的选择、参数解析和递归创建Advisor对象,如AspectJPointcutAdvisor,这些Advisor可能需要其他依赖对象,如AbstractAspectJAdvice,进而触发更多对象的实例化。整个过程是一个深度优先的递归构造过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建对象

准备好了Aop相关的BeanDefinition了,开始实例化了。

refresh()->finishBeanFactoryInitialization(beanFactory)->preInstantiateSingletons()

public void preInstantiateSingletons() throws BeansException {
    //................
    for (String beanName : beanNames) {
        //..........
       getBean(beanName); 
    }
    
}

->doGetBean(...) ->createBean(beanName, mbd, args)
AbstractAutowireCapableBeanFactory.java#createBean(.....)

//从创建 LogUtil 开始
@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
try {
    //.....
	   // 给BeanPostProcessors一个机会来返回代理来替代真正的实例
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
        
 	  // 实际创建bean的调用
   Object beanInstance = doCreateBean(beanName, mbdToUse, args);	
	//......	
}

----->
    
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) 	{
    //......
		Object bean = null;
		// 判断当前mbd是否是合成的,只有在实现aop的时候synthetic的值才为true,并且是否实现了                 InstantiationAwareBeanPostProcessor接口
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			// 获取类型
		  Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) { // 可以在postprocessor提前去创建对象
                //调用
			   bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
			//......
                }
		return bean;
}
	@Nullable
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

对于AspectJAwareAdvisorAutoProxyCreator.java类是符合要求的,那么进去到方法中去执行
在这里插入图片描述
-> ibp.postProcessBeforeInstantiation(beanClass, beanName)AbstractAutoProxyCreator.java的方法(是父类的方法)

AbstractAutoProxyCreator.java#postProcessBeforeInstantiation(…)

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		//...........................
		//shouldSkip 子类(本例AspectJAwareAdvisorAutoProxyCreator)复写,调用子类自己的。
     //实例化XXXAdvisor 对象,各种Advisor都是有参的构造方案(需要把构造器中需要的对象都要提前创建好,所以需要各种递归了)
			// 是基础设施类,往下走了继续
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				// 要跳过的直接设置FALSE
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
		}
    //......    .......................
}          

其中,开始创建XXadvisor
AspectJAwareAdvisorAutoProxyCreator.java#shouldSkip(…)

	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
   //.....
}

->BeanFactoryAdvisorRetrivaHelper.java#findAdvisorBeans()

//查找所有的XXAdvisor.class 的bean名字,创建
public List<Advisor> findAdvisorBeans() {
    // 对获取到的实现Advisor接口的bean的名称进行遍历
		List<Advisor> advisors = new ArrayList<>();
		// 循环所有的beanName,找出对应的增强方法
		for (String name : advisorNames) {
         //...........................
			try {
				// 将当前bean添加到结果中
				// 涉及整个XXadvisor 的创建。(循环创建XXAdvisor 对象)
                //例如:name是org.springframework.aop.aspectj.AspectJPointcutAdvisor#0
				advisors.add(this.beanFactory.getBean(name, Advisor.class));
             }
		}
          //...........................   
}

假如创建AspectJPointcutAdvisor.java对象,该类没有无参数构造函数。那么需要创建对应的入参对象了

public AspectJPointcutAdvisor(AbstractAspectJAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
		this.pointcut = advice.buildSafePointcut();
	}
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
public class AspectJAfterAdvice extends AbstractAspectJAdvice    
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
public class AspectJAroundAdvice extends AbstractAspectJAdvice
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice
       
 // 其它结构构造函数类似,没有无参构造函数   
public AspectJMethodBeforeAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
	super(aspectJBeforeAdviceMethod, pointcut, aif);
}    

需要AbstractAspectJAdvice 类型的参数,所以创建流程

2. 某个对象创建

找到合适的构造方法,如果构造方法是有参的,那么需要解析参数(涉及对象的创建)

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
    //.......................
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    //.......
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
     
}

---->doCreateBean(…)

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
    //.............
   	// 根据执行bean使用对应的策略创建新的实例,如,工厂方法,构造函数主动注入、简单初始化
	  instanceWrapper = createBeanInstance(beanName, mbd, args);
	// 从包装类中获取原始bean
	Object bean = instanceWrapper.getWrappedInstance();    
}

—>createBeanInstance(…) 查找合适的构造方法

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   //.....................
	// 从bean后置处理器中为自动装配寻找构造方法, 有且仅有一个有参构造或者有且仅有@Autowired注解构造
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		// 以下情况符合其一即可进入
		// 1、存在可选构造方法
		// 2、自动装配模型为构造函数自动装配
		// 3、给BeanDefinition中设置了构造参数值(构造函数有参数)
		// 4、有参与构造函数参数列表的参数
		if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
			//这里面解析参数,找到构造方法,开始处理构造方法中的参数
			// -》 没有的话,开始调用createBean(..)
			return autowireConstructor(beanName, mbd, ctors, args);
		}
		// Preferred constructors for default construction?
		// 找出最合适的默认构造方法
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			// 构造函数自动注入
			return autowireConstructor(beanName, mbd, ctors, null);
		}
		// 使用默认无参构造函数创建对象,
		return instantiateBean(beanName, mbd);

}

解析构造函数,需要实例化的继续循环调用。

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
    
    //...............
    // 提取配置文件中的配置的构造函数参数
	ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
    // 能解析到的参数个数(涉及了构造方法中,参数是mbd的时候,要先实例化成对象了)
	//******开始处理参数,mdb的话,要涉及创建了******
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
   
	// 将构造的实例加入BeanWrapper中。
	// 这里将上面准备好的参数,实例化
	bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
    
}    

处理参数中的bd信息,有创建对象操作valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); 创建对象,又开始循环操作,然后依次返回

private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
    //...
    // 遍历参数,设置了索引的位置参数。有实例化的操作(当发现是mbd的时候)
	for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : 							cargs.getIndexedArgumentValues().entrySet()) { 
       //....
	// 是mbd的话,涉及对象的创建
     Object resolvedValue =valueResolver.resolveValueIfNecessary("constructor 				      argument", valueHolder.getValue());
     }
    //............
    // 普通情况
	for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
        //参数bd,创建成对象(又开始getBean->。。。。。doCreateBean()->createInstance())
    Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", 			valueHolder.getValue());
    }
    	// 返回最小(索引参数值数+泛型参数值数)
		return minNrOfArgs;
}    

3.总结

  1. 创建AspectJPointcutAdvisor#0等,先使用其带参的构造方法进行对象的创建,但是想使用带参数的构造方法,必须要把参数对象准备好,因此要准备创建内置包含的对象AspectJAroundAdvice(等其它4个是一样的,此处仅用于举例)
  2. 创建AspectJAroundAdvice,也需要使用带参的构造方法进行创建,也需要提前准备好具体的参数对象,包含三个参数:
  • MethodLocatingFactoryBean
  • AspectJExpressionPointcut
  • SimpleBeanFactoryAwareAspectInstanceFactory
  1. 分别创建上述的三个对象,上述三个对象的创建过程都是调用无参的构造方法,直接反射生成即可
    其实是一个循环递归的流程
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值