Aop源码解析(二)核心对象创建
创始人
2024-06-02 08:05:08
0

创建对象

准备好了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 开始
@Overrideprotected 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;
}
	@Nullableprotected 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)) {// 要跳过的直接设置FALSEthis.advisedBeans.put(cacheKey, Boolean.FALSE);return null;}//......    .......................
}          

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

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

->BeanFactoryAdvisorRetrivaHelper.java#findAdvisorBeans()

//查找所有的XXAdvisor.class 的bean名字,创建
public List findAdvisorBeans() {// 对获取到的实现Advisor接口的bean的名称进行遍历List advisors = new ArrayList<>();// 循环所有的beanName,找出对应的增强方法for (String name : advisorNames) {//...........................try {// 将当前bean添加到结果中// 涉及整个XXadvisor 的创建。(循环创建XXAdvisor 对象)//例如:name是org.springframework.aop.aspectj.AspectJPointcutAdvisor#0advisors.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);// 从包装类中获取原始beanObject 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 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篇)  根据活动对象的不同,需要设置不同的主持词。在当今社会中,司仪等...
追悼会程序及主持词 有关追悼会程序及主持词  中国人无论做什么事情,都十分讲究仪式。下面小编带来的是有关追悼会程序及主持...
答谢宴简短致辞 答谢宴简短致辞范文(通用15篇)  在平平淡淡的学习、工作、生活中,大家对致辞都不陌生吧,致辞具有“...
六一主持词开场白 六一主持词开场白  送去五月的芬芳,迎来六月的时光,六一儿童节即将来临,以下是由应届毕业生网PQ小编...
郭德纲相声论梦台词 郭德纲相声论梦台词  郭德纲出现引起了社会对相声关注,很多人对相声感兴趣,开始思考相声中问题。下面是...
学校元旦经典致辞 学校元旦经典致辞范文(精选5篇)  在我们平凡的日常里,大家一定都接触过致辞吧,致辞的措词造句要考虑...
快板台词 快板台词大全  快板是一种汉族说唱艺术,属于中国曲艺韵诵类曲种。早年称作“数来宝”,也叫称“顺口溜”...
读书活动主持词开场白   读书活动主持词开场白1  尊敬的各位领导、各位来宾、各位参赛选手:  大家下午好!在春意盎然,百...
感谢老师致辞 感谢老师致辞(精选12篇)  在平日的学习、工作和生活里,要用到致辞的地方还是很多的,致辞是指在举行...
结婚典礼感谢致辞 结婚典礼感谢致辞(通用15篇)  在平平淡淡的学习、工作、生活中,要用到致辞的情况还是蛮多的,致辞要...
大鱼海棠配音台词 大鱼海棠配音台词  蛰伏十二年的动画《大鱼海棠》,终于上映了。虽然剧情被很多人吐槽,但美得不像话的画...
小学毕业典礼主持词 小学毕业典礼主持词实用范文  活动对象的不同,主持词的写作风格也会大不一样。在当今中国社会,司仪等是...
篮球赛闭幕词 篮球赛闭幕词(精选15篇)篮球赛闭幕词1各位来宾、同志们:  为期xx天的xxx第二届职工篮球赛,在...
元旦联欢晚会主持词 元旦联欢晚会主持词范文(精选9篇)  主持词分为会议主持词、晚会主持词、活动主持词、婚庆主持词等。在...
大型文艺演出主持词 大型文艺演出主持词  主持词可以采用和历史文化有关的表述方法去写作以提升活动的文化内涵。在当今中国社...
开学典礼致辞 开学典礼致辞15篇  在日常生活或是工作学习中,大家都经常接触到致辞吧,致辞具有“礼仪性”或“仪式化...
农村婚礼司仪主持词 农村婚礼司仪主持词15篇  主持词需要富有情感,充满热情,才能有效地吸引到观众。在当今不断发展的世界...
如何主持会议参考 如何主持会议范文参考  1.宣布会议开始。会议时间到后,若全体与会人员都已到位(至少重要的与会人员已...
韩剧漂亮男人经典台词 韩剧漂亮男人经典台词  1、答案都是在当事人手里的,不知道人们为什么,明明是自己非常了解的问题,但是...
外公七十大寿祝寿词 外公七十大寿祝寿词  外公七十大寿祝寿词  尊敬的外公、外婆、各位长辈、各位来宾:    大家好!今...