Spring的bean实例化过程

以XmlBeanFactory为例,最简单的取bean方式是:

BeanFactory factory = new XmlBeanFactory(new FileSystemResource("D:\\workspace\\JavaApplication2\\src\\javaapplication2\\spring\\beans.xml"));  Car obj = (Car)factory.getBean("car");  

Bean的配置文件内容也很简单:

<bean id="vehicle"   abstract="true">  <property name="wheel" value="Four wheeler"/>          
</bean>  
<bean id="car" class="javaapplication2.spring.Car" parent="vehicle">  <property name="dicky" value="Flat dicky"/>      
</bean>  

先看起始点,载入先走AbstractBeanFactory

public Object getBean(String name) throws BeansException {  return doGetBean(name, null, null, false);  
}  

doGetBean方法中:

// Create bean instance.  
if (mbd.isSingleton()) {  //传入一个内联类ObjectFactory并实现了getObject方法。  sharedInstance = getSingleton(beanName, new ObjectFactory() {  public Object getObject() throws BeansException {  try {  return createBean(beanName, mbd, args);  }  catch (BeansException ex) {  // Explicitly remove instance from singleton cache: It might have been put there  // eagerly by the creation process, to allow for circular reference resolution.  // Also remove any beans that received a temporary reference to the bean.  destroySingleton(beanName); //有异常则销毁bean  throw ex;  }  
}  
});  bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  //此处开始实例化bean  

通过new ObjectFactory()的回调方法,回调当前类继承的createBean方法,该方法在父类AbstractAutowireCapableBeanFactory中:

AbstractAutowireCapableBeanFactory->

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)  throws BeanCreationException {  // Make sure bean class is actually resolved at this point.  resolveBeanClass(mbd, beanName);  //载入该bean的class,并放置到mbd里面,bean的生成不在这里。  // Prepare method overrides.  try {  mbd.prepareMethodOverrides();  }  catch (BeanDefinitionValidationException ex) {  throw new BeanDefinitionStoreException(mbd.getResourceDescription(),  beanName, "Validation of method overrides failed", ex);  }  try {  // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.  Object bean = resolveBeforeInstantiation(beanName, mbd);  //尝试获取一个proxy,普通bean这里一般是空的返回  if (bean != null) {  return bean;  }  }  catch (Throwable ex) {  throw new BeanCreationException(mbd.getResourceDescription(), beanName,  "BeanPostProcessor before instantiation of bean failed", ex);  }  Object beanInstance = doCreateBean(beanName, mbd, args);  //开始create bean的实例,mbd中包括了需要的class  if (logger.isDebugEnabled()) {  logger.debug("Finished creating instance of bean '" + beanName + "'");  }  return beanInstance;  }  

进入AbstractBeanFactory中的protected Class resolveBeanClass方法:

try {  if (mbd.hasBeanClass()) {  return mbd.getBeanClass();  }  if (System.getSecurityManager() != null) {  return AccessController.doPrivileged(new PrivilegedExceptionAction<Class>() {  public Class run() throws Exception {  return doResolveBeanClass(mbd, typesToMatch);  }  }, getAccessControlContext());  }  else {  return doResolveBeanClass(mbd, typesToMatch);   <---还要继续进去看生成方法。  }  
}  

转入doResolveBeanClass:

private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch) throws ClassNotFoundException {  if (!ObjectUtils.isEmpty(typesToMatch)) {  ClassLoader tempClassLoader = getTempClassLoader();  if (tempClassLoader != null) {  if (tempClassLoader instanceof DecoratingClassLoader) {  DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;  for (Class<?> typeToMatch : typesToMatch) {  dcl.excludeClass(typeToMatch.getName())  }  }  String className = mbd.getBeanClassName();  return (className != null ? ClassUtils.forName(className, tempClassLoader) : null); //通过自己的ClassUtils的forName方法来实例化class  }  }  return mbd.resolveBeanClass(getBeanClassLoader());  <----这里传入了bean的classloader,下面继续看这里  
}  

AbstractBeanDefinition->resolveBeanClass

public Class resolveBeanClass(ClassLoader classLoader) throws ClassNotFoundException {  String className = getBeanClassName();  if (className == null) {  return null;  }  Class resolvedClass = ClassUtils.forName(className, classLoader);//classloader传入后,仍然是用forName方法加载class  this.beanClass = resolvedClass;  return resolvedClass;  }  

再来看forName做了些什么

ClassUtils ->

ClassLoader classLoaderToUse = classLoader;  
if (classLoaderToUse == null) {  classLoaderToUse = getDefaultClassLoader();  
}  
try {  return classLoaderToUse.loadClass(name); //也比较简单,直接调用loadClass方法加载  
}  

最终将class load进来。

进入

AbstractAutowireCapableBeanFactory->instantiateBean

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd)  
...这里省略没用的        else {  beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);//下面看这里的实例化  }         BeanWrapper bw = new BeanWrapperImpl(beanInstance);   //返回一个包装类对象  initBeanWrapper(bw);  return bw;  

SimpleInstantiationStrategy->instantiate

public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner)  synchronized (beanDefinition.constructorArgumentLock) {  constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;  ...  }  return BeanUtils.instantiateClass(constructorToUse);     //BeanUtils来初始化实例 ,给出了实例化需要的构造函数  

再来看BeanUtils的实例化方法,比较简单,直接用反射的构造函数来newInstance。

BeanUtils->

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {  try {  ReflectionUtils.makeAccessible(ctor);  return ctor.newInstance(args);  }  

AbstractAutowireCapableBeanFactory->

Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)   // Initialize the bean instance.  Object exposedObject = bean;  try {  populateBean(beanName, mbd, instanceWrapper);  if (exposedObject != null) {  exposedObject = initializeBean(beanName, exposedObject, mbd);  }  }  return exposedObject;       //返回给AbstractBeanFactory  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/250043.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最全整理浏览器兼容性问题与解决方案(转)

所谓的浏览器兼容性问题&#xff0c;是指因为不同的浏览器对同一段代码有不同的解析&#xff0c;造成页面显示效果不统一的情况。在大多数情况下&#xff0c;我们的需求是&#xff0c;无论用户用什么浏览器来查看我们的网站或者登陆我们的系统&#xff0c;都应该是统一的显示效…

【算法】 - 滑动窗口

1. 题目链接 2. 分析 最多可以将K个值从0变成1,因此滑动窗口的限制条件: 0的数量(zeros)小于K,算法过程如下 有一个滑动窗口(slipper),每次都会从A中读入一个数当读入的数为0时,zeros当zeros的数量大于K时,会取出slipper首部的元素,当取值为0时zeros-- 总体代码如下: var lo…

Springboot整合thymeleaf模板

Thymeleaf是个XML/XHTML/HTML5模板引擎&#xff0c;可以用于Web与非Web应用。 Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式&#xff0c;因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码&#xff0…

Java代码输出到txt文件(申请专利贴源码的必备利器)

最近公司在申请专利&#xff0c;编写不少文档&#xff0c;项目的代码量实在是过于庞大。如果一个一个的复制粘贴虽然能够完成&#xff0c;但是对于程序员而言实在没有这个必要。shell或者python就能解决这个问题。由于我个人对于shell和python不是非常熟练的情况下&#xff0c;…

【算法】 - 动态规划 + 位运算

题目描述 思路1: 写一个返回2进制中1数量的函数countOne遍历0到num,对每一个数使用countOne,并将结果保存到res中返回 var countBits function (num) {let res new Array(num 1).fill(0);for (let i 0; i < num; i) {res[i] countOne(i.toString(2));}return res; };…

Spring配置AOP切入点execution详解

例&#xff1a; execution (* com.sample.service…*. *(…)) 整个表达式可以分为五个部分&#xff1a; 1、execution():&#xff1a;表达式主体。 2、第一个*号&#xff1a;表示返回类型&#xff0c; *号表示所有的类型。 3、包名&#xff1a;表示需要拦截的包名&#xff…

Netty

1BS/CS? 2断点续传需要activeX,需要独立客户端有状态,tomcat无状态,或者Netty有状态,可以断点续传 3Netty核心java nio性能比较高 4Jetty和Netty和dubbo区别? 5 转载于:https://www.cnblogs.com/xinglongbing521/p/10105351.html

sympy科学计算器

SymPy库常用函数 简介 本文抄于https://www.cnblogs.com/baby123/p/6296629.html SymPy是一个符号计算的Python库。它的目标是成为一个全功能的计算机代数系统&#xff0c;同时保持代码简 洁、易于理解和扩展。它完全由Python写成&#xff0c;不依赖于外部库。SymPy支持符号计算…

【异或运算】 - 交换2个数

1. 代码 let a 3; let b 4; a a ^ b; b a ^ b; a a ^ b;2. 异或的性质 不同为1,相同为0(可以看做是无进制位的加法)交换律: a ^ b b ^ a;结合律: (a ^ b) ^ c a ^ (b ^ a);0 ^ x x;x ^ x 0; 3. 证明 下面证明1中的代码 a 3 ^ 4;b (3 ^ 4) ^ 4 3 ^ 0 3;a (3…

Spring底层控制反转解耦合(IOC)

简单的例子解释IOC控制反转进行解耦合 一、相关概念 &#xff08;1&#xff09;解耦合 解耦合就是把程序中互相不相关或有限相关的模块分割开来&#xff0c;把不同模块互相之间的关系用接口进行准确定义&#xff0c;解耦前&#xff0c;两个模块之间共享所有信息&#xff1b; &…

Manacher算法学习笔记 | LeetCode#5

Manacher算法学习笔记 DECLARATION 引用来源&#xff1a;https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途&#xff1a;寻找一个字符串的最长回文子串时间复杂度&#xff1a;O(N)算法步骤&#xff1a; 1.添加特殊字符 由于回文串的长度可奇可偶&#xff0c;比如…

content-type对照表

转载于:https://www.cnblogs.com/mxyr/p/9238329.html

【算法小积累】 - 提取非0数最右侧的1

参考 - 69:49 const getRightOne num > {return num & (~num 1); };

解耦合

广大程序猿同胞&#xff0c;经常会看到“解耦合”&#xff0c;也有很多人&#xff0c;会用这个词来装X&#xff0c;但是&#xff0c;实际真正能理解的人&#xff0c;并不多。接下来&#xff0c;带大家深入浅出的走一遍&#xff0c;如何解耦合。 首先&#xff0c;我们要知道&am…

CentOS安装和配置Rsync进行文件同步

Liunx系统实现文件同步不需要搭建FTP这类的工具&#xff0c;只需要按照Rsync配置下文件就可以。 本文以Centos7.0为例。 1. 首先关闭SELINUX&#xff08;不关闭无法同步&#xff0c;权限太高了&#xff09; vi /etc/selinux/config #编辑防火墙配置文件 #SELINUXenforcing #注释…

【linux】 -设备名称与文件目录

参考 - 鸟哥的linux私房菜基础篇 在linux系统中,每个设备都被当成一个文件来对待几乎所有的硬件设备文件都在/dev这个目录内 下面给出,常见设备和文件路径的对应关系 设备设备在Linux中的文件名SCSI、SATA、USB磁盘驱动器/dev/sd[a-p]U盘/dev/sd[a-p] (与SATA相同)Virtio接口/…

数据结构开发(7):典型问题分析(Bugfix)

0.目录 1.创建异常对象时的空指针问题 2.LinkList 中的数据元素删除 3.LinkList 中遍历操作与删除操作的混合使用 4.StaticLinkList 中数据元素删除时的效率问题 5.StaticLinkList 是否需要提供析构函数&#xff1f; 6.StLib 是否有必要增加多维数组类&#xff1f; 1.创建异常对…

spring boot 使用视图modelandview

1&#xff1a;springboot使用视图解析器&#xff0c;添加依赖 <!-- freemarker模板引擎视图 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency>&…

题解-BOI 2004 Sequence

Problem bzoj & Luogu 题目大意&#xff1a; 给定序列\(\{a_i\}\)&#xff0c;求一个严格递增序列\(\{b_i\}\)&#xff0c;使得\(\sum \bigl |a_i-b_i\bigr|\)最小 Thought 正序&#xff1a;直接对应 逆序&#xff1a;取中位数&#xff08;证明&#xff1a;“医院设置”&am…

【vscode】编译java时报错乱码

报错如下 解决方案 改变终端的编码格式 chcp 946注意: chcp 65001 UTF-8编码chcp 936 GBK2312代码页