当前位置: 首页 > news >正文

做烘培的网站品牌咨询

做烘培的网站,品牌咨询,免费软件下载公众号,苏州 中英文网站建设上一篇Spring源码二十一:Bean实例化流程四,咱们主要分析里createBeanInstance方法Spring给我们提供给的FactoryMethod方法,举例说明了factoryMethod属性如何使用,同时简单讨论了具体实现逻辑。 这一篇咱们将进入反射实例化Bean&am…

上一篇Spring源码二十一:Bean实例化流程四,咱们主要分析里createBeanInstance方法Spring给我们提供给的FactoryMethod方法,举例说明了factoryMethod属性如何使用,同时简单讨论了具体实现逻辑。

这一篇咱们将进入反射实例化Bean:


createBeanInstance构造推断

// 如果有多个构造方法,通过该方法查找对应的构造法方法Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?// 获取首选的构造函数列表ctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}// No special handling: simply use no-arg constructor.// 用无参构造函数来创建bean,先进入这个方法看下return instantiateBean(beanName, mbd);

 查找构造方法

determineConstructorsFromBeanPostProcessors 方法会调用BeanPostProcessor来查找与给定Bean类和Bean名称对应的构造函数。如果找到了一个或多个构造方法,或者满足以下任何一个条件:

如果满足其中任何一个条件,则调用 autowireConstructor 方法来通过构造函数自动装配来实例化Bean。

  • mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR:自动装配模式为构造函数自动装配。
  • mbd.hasConstructorArgumentValues():Bean定义中有构造函数参数值。
  • !ObjectUtils.isEmpty(args):构造函数参数不为空。

获取首选的构造函数

如果前面的条件不满足,代码会尝试获取首选的构造函数列表。如果存在首选的构造函数,也会调用 autowireConstructor 方法来实例化Bean。

使用无参构造函数

如果既没有找到构造方法,也没有指定构造函数参数,则使用无参构造函数来创建Bean。调用 instantiateBean 方法来实例化Bean对象。

instantiateBean

/*** 使用默认构造实例化一个bean* 首先使用instantiate方法实例化一个beanInstance* 然后构建一个BeanWrapper* 返回BeanWrapper对象** Instantiate the given bean using its default constructor.** @param beanName the name of the bean* @param mbd the bean definition for the bean* @return a BeanWrapper for the new instance*/protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {try {Object beanInstance;final BeanFactory parent = this;if (System.getSecurityManager() != null) {beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->getInstantiationStrategy().instantiate(mbd, beanName, parent),getAccessControlContext());}else {// 核心的方法是instantiatebeanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);}BeanWrapper bw = new BeanWrapperImpl(beanInstance);initBeanWrapper(bw);return bw;}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);}}
上述代码也是比较清晰的,咱们来简单分析一下:通过默认构造函数来实例化一个Bean,并将该Bean封装在一个 BeanWrapper 实例中。它首先检查系统是否启用了安全管理器,如果启用,则在特权模式下实例化Bean;否则,直接实例化。最后,它会对 BeanWrapper 进行初始化并返回。如果在此过程中出现任何异常,方法会捕获并抛出一个 BeanCreationException。

instantiate

通过上述分析,咱们接着进入instantiate方法看下。

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.//if (!bd.hasMethodOverrides()) {Constructor<?> constructorToUse;synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {final Class<?> clazz = bd.getBeanClass();if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {if (System.getSecurityManager() != null) {constructorToUse = AccessController.doPrivileged((PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);}else {constructorToUse = clazz.getDeclaredConstructor();}bd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}// 实例化beanreturn BeanUtils.instantiateClass(constructorToUse);}else {// Must generate CGLIB subclass.return instantiateWithMethodInjection(bd, beanName, owner);}}

上述代码:首先检查 bd 是否有方法重写,如果没有则采用直接实例化的方式。通过同步块确保构造函数解析的线程安全性,尝试获取默认构造函数。如果类是接口或没有默认构造函数,则抛出异常。成功获取构造函数后,通过 BeanUtils.instantiateClass 方法实例化 bean。如果有方法重写,则使用 CGLIB 动态生成子类进行实例化。

我们再进入BeanUtils.instantiateClass方法中看下:


BeanUtils.instantiateClass

{Assert.notNull(ctor, "Constructor must not be null");try {ReflectionUtils.makeAccessible(ctor);if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {return KotlinDelegate.instantiateClass(ctor, args);}else {Class<?>[] parameterTypes = ctor.getParameterTypes();Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");Object[] argsWithDefaultValues = new Object[args.length];for (int i = 0 ; i < args.length; i++) {if (args[i] == null) {Class<?> parameterType = parameterTypes[i];argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);}else {argsWithDefaultValues[i] = args[i];}}// 通过反射来实例化一个bean实例return ctor.newInstance(argsWithDefaultValues);}}catch (InstantiationException ex) {throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);}catch (IllegalAccessException ex) {throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);}catch (IllegalArgumentException ex) {throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);}catch (InvocationTargetException ex) {throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());}}

上述代码可以看到:首先确保传入的构造函数不为 null,并通过 ReflectionUtils.makeAccessible 方法确保构造函数可访问。如果类是 Kotlin 类型,则通过 KotlinDelegate.instantiateClass 方法实例化,这块可以直接跳古偶。

否则,检查参数长度并为 null 参数赋默认值,然后调用构造函数创建实例。若实例化过程中出现异常,则抛出相应的 BeanInstantiationException 异常,提示可能的错误原因,如类是否为抽象类、构造函数是否可访问、参数是否合法或构造函数是否抛出异常。

小结 

今天咱们主要了解到bean在实例化之前会推测构造方法,然后根据构造方法的类型来通过反射机制来完成具体的实例化。到这里咱们终于看到了实例化的bean,接下来Spring会对这个刚刚实例化好的bean做些什么呢?

总结

http://www.yayakq.cn/news/403724/

相关文章:

  • 设计公司企业网站详情wordpress做中英文站
  • 自己做的网站上传到不得不知道的网站
  • 网站开发和软件博物馆网站建设依据
  • 电商网站的建设动态温州专业网站制作设计
  • 网页美工制作网站无锡做公司网站
  • 网站建设遇到哪些攻击500套wordpress模板
  • 备案网站到期了怎么办网站建设捌金手指下拉四
  • 免费建站网站教程物流的网站模板
  • 深圳建设工程信息网站可以看禁止访问网站的浏览器
  • 移动端网站设计前有哪些准备工作?网站点内页还是首页
  • 各大网站开发语言南宁公司注册网上核名
  • 网站商城支付宝开通怎么做网站的建设与开发
  • 个人网站可以做seo吗android 网站模板下载
  • 亚马逊网站开发使用的什么方式郑州建设高端网站
  • 装修公司合作平台的网站叫别人建个网站多少钱
  • seo站长工具平台网站推广教程优化整站
  • html企业网站怎么做搭建本地网站环境
  • 制作网站找云优化深圳seo公司助力网络营销飞跃
  • 企业为什么建站网站后台找不到了怎么办
  • ppt免费模板大全网站简述网站与网页的区别
  • 电商网站设计系列asp网站开发视频教程
  • 社交网站设计北京小程序外包
  • 成都网站建设kaituozuwordpress密码设置不
  • 什么网站可以免费做会计初级林州网站建设熊掌号
  • 如何免费创建网站枣庄建设路小学网站
  • 大尺度做爰后入网站网站工作室模板
  • 电子厂家网站建设wordpress换字体
  • 重庆电子商务网站网络结构分几层
  • 推荐聊城做网站的公司网站打开慢
  • 邯郸公司起名我们seo