首页 > 编程语言 >Spring源码(八)--Spring实例化的策略

Spring源码(八)--Spring实例化的策略

时间:2024-07-30 23:50:36浏览次数:13  
标签:java -- Spring support Object factory springframework 源码 org

Spring实例化的策略有几种 ,可以看一下 InstantiationStrategy 相关的类。

UML 结构图

InstantiationStrategy的实现类有 SimpleInstantiationStrategy。 CglibSubclassingInstantiationStrategy 又继承了SimpleInstantiationStrategy。

在这里插入图片描述

InstantiationStrategy

InstantiationStrategy . 实例化的策略, 可以根据 给定名称及默认的构造函数、 或者是指定的构造函数、 工厂方法 实例化。

InstantiationStrategy 源码如下:


/**
  * 负责创建与基础bean定义相对应的实例。
  */
public interface InstantiationStrategy {

	/**
	 *  根据给定名称,返回该工厂中的bean实例。使用默认的构造函数。
	 */
	Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
			throws BeansException;

	/**
	 * 返回该工厂中具有给定名称的bean实例,并通过给定构造函数创建它。
	 */
	Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			Constructor<?> ctor, @Nullable Object... args) throws BeansException;

	/**
	 * 返回该工厂中具有给定名称的bean实例,并通过给定的工厂方法创建它。
	 */
	Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Object factoryBean, Method factoryMethod, @Nullable Object... args)
			throws BeansException;

}

SimpleInstantiationStrategy

InstantiationStrategy 实现了 SimpleInstantiationStrategy.

SimpleInstantiationStrategy 调用的方法栈如下:

	  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:155)
	  at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
	  at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486)
	  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
	  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
	  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
	  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	  at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	  at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$195.404947798.getObject(Unknown Source:-1)
	  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213)
	  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:171)
	  at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
	  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
	  at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
	  at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:745)
	  at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:420)
	  at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
	  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1317)
	  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)



  • ConstructorResolver.instantiate 实例化:
    ConstructorResolver.instantiate 会先获取对应的策略,然后再实例化。

方法具体路径:
org.springframework.beans.factory.support.ConstructorResolver#instantiate(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object, java.lang.reflect.Method, java.lang.Object[])

代码如下:

	private Object instantiate(String beanName, RootBeanDefinition mbd,
			@Nullable Object factoryBean, Method factoryMethod, Object[] args) {

		try {
			if (System.getSecurityManager() != null) {
				return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						this.beanFactory.getInstantiationStrategy().instantiate(
								mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
						this.beanFactory.getAccessControlContext());
			}
			else {
				// 关键看这一句, 先获取对应的策略,然后再实例化。
				return this.beanFactory.getInstantiationStrategy().instantiate(
						mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean instantiation via factory method failed", ex);
		}
	}

接下来会调用 SimpleInstantiationStrategy#instantiate 。

org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory, java.lang.Object, java.lang.reflect.Method, java.lang.Object...)

通过反射, 设置 bean 的属性值, 进行 实例化.

如下:

	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Object factoryBean, final Method factoryMethod, Object... args) {

		try {
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					ReflectionUtils.makeAccessible(factoryMethod);
					return null;
				});
			}
			else {
				ReflectionUtils.makeAccessible(factoryMethod);
			}
			// 重点看这里, 反射,进行实例化.
			// currentlyInvokedFactoryMethod 的类型是 ThreadLocal<Method>  ,以此保证线程安全.
			Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
			try {
				currentlyInvokedFactoryMethod.set(factoryMethod);
				// 通过反射, 设置 bean 的属性值
				Object result = factoryMethod.invoke(factoryBean, args);
				if (result == null) {
					result = new NullBean();
				}
				// 返回实例化的 bean.
				return result;
			}
			finally {
				if (priorInvokedFactoryMethod != null) {
					currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
				}
				else {
					currentlyInvokedFactoryMethod.remove();
				}
			}
		}
		catch (IllegalArgumentException ex) {
			throw new BeanInstantiationException(factoryMethod,
					"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
					"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
		}
		catch (IllegalAccessException ex) {
			throw new BeanInstantiationException(factoryMethod,
					"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
		}
		catch (InvocationTargetException ex) {
			String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
			if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
					((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
				msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
						"declaring the factory method as static for independence from its containing instance. " + msg;
			}
			throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
		}
	}

CglibSubclassingInstantiationStrategy

CglibSubclassingInstantiationStrategy 实现了 SimpleInstantiationStrategy.

CglibSubclassingInstantiationStrategy 实例化 bean 的代码如下:

				
		/**
		  *     实例化, 动态生成
		  */
		public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
			Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
			Object instance;
			if (ctor == null) {
				instance = BeanUtils.instantiateClass(subclass);
			}
			else {
				try {
					// 实例化
					Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
					instance = enhancedSubclassConstructor.newInstance(args);
				}
				catch (Exception ex) {
					throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
							"Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
				}
			}
			Factory factory = (Factory) instance;
			factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
					new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
					new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
			return instance;
		}

标签:java,--,Spring,support,Object,factory,springframework,源码,org
From: https://www.cnblogs.com/expiator/p/18333594

相关文章

  • POSIX-shell学习笔记
    学习POSIXshell建议使用dash,因为它很快:https://unix.stackexchange.com/a/148098mandash:OnlyfeaturesdesignatedbyPOSIX,plusafewBerkeleyextensions,arebeingincorporatedintothisshell.条件判断mandash,然后搜索testexpression,可以看到完整的列表。ife......
  • 关于new、delete函数的错误处理(std::nothrow)
    new、delete函数源码注释如下:无参数无参数的new、delete函数,如果调用失败,会抛出bad_alloc异常,需要使用try{}catch(){}语句捕获异常从而进行异常处理。#include<iostream>intmain(){try{while(1){int*p=newint[100000000ul];......
  • Laconic Private Set-Intersection From Pairings (2022)
    LaconicPrivateSet-IntersectionFromPairings(2022)论文地址:https://eprint.iacr.org/2022/529.pdf代码地址:https://github.com/relic-toolkit/relic/tree/main/demo/psi-client-server代码运行参考:RELIC库学习Laconic算法介绍Laconic适用于算力和存储受限的客户端......
  • docker换国内镜像源-Docker安装 Nginx测试-Docker部署Gitblit服务器
    docker换国内镜像源,docker换源echo>/etc/docker/daemon.jsoncat>/etc/docker/daemon.json<<END{  "registry-mirrors":[    "https://hub-mirror.c.163.com",    "https://ustc-edu-cn.mirror.aliyuncs.com",    "https:/......
  • 全网最适合入门的面向对象编程教程:28 类和对象的Python实现-Python编程原则、哲学和规
    全网最适合入门的面向对象编程教程:28类和对象的Python实现-Python编程原则、哲学和规范大汇总摘要:本文主要介绍了在使用Python进行面向对象编程时,Python异常处理的原则-“请求谅解,而非许可”,以及软件设计和Python的编程原则,同时介绍了PEP8规范。原文链接:FreakStud......
  • 了解GraphRAG
    了解GraphRAG转载:从零实现大模型-GraphRAG,构建LLM中的关系数据库开源地址:https://github.com/microsoft/graphrag论文:FromLocaltoGlobal:AGraphRAGApproachtoQuery-FocusedSummarization博客介绍:https://microsoft.github.io/graphrag/传统RAGLLM预训练和......
  • [vue3] Vue3源码阅读笔记 reactivity - collectionHandlers
    源码位置:https://github.com/vuejs/core/blob/main/packages/reactivity/src/collectionHandlers.ts这个文件主要用于处理Set、Map、WeakSet、WeakMap类型的拦截。拦截是为了什么?为什么要处理这些方法?Vue3实现响应式的思路是使用ProxyAPI在getter中收集依赖,在setter触发更新......
  • python生成器
    一前言环境:python3.10win10二生成器1关于生成器先看一个例子    定义了一个函数,当我们运行该函数时,并未像普通函数那样执行函数体内的代码    从其中的英文可知,执行函数得到了一个生成器对象,这个生成器对象也叫做generatoriterator(生成器迭代器),generatorit......
  • C程序起点main函数
    C程序起点main函数mainc语言中main函数接收两个参数intargc,char*argv[]intmain(intargc,char*argv[]);intmain(intargc,char**argv);如上,argc代表参数的数量,argv但是参数字符串指针数组./program-i192.168.0.1-p2000此时共有五个参数,argv[0]-->./prog......
  • 八股文”在实际工作中是助力、阻力还是空谈?
    “八股文”在实际工作中是助力、阻力还是空谈?作为现在各类大中小企业面试程序员时的必问内容,“八股文”似乎是很重要的存在。但“八股文”是否能在实际工作中发挥它“敲门砖”应有的作用呢?有IT人士不禁发出疑问:程序员面试考什么?是工作能力、工作经验还是背题能力?还有程序员吐......