bean的创建(五)第四部分 bean构造器的查找
- 前面分析了bean的静态工厂查找
- bean的构造器查找过程和bean的静态工厂查找类似
- protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
- // Make sure bean class is actually resolved at this point.
- Class<?> beanClass = resolveBeanClass(mbd, beanName);
- if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
- }
- if (mbd.getFactoryMethodName() != null) {
- //使用工厂方法获取
- return instantiateUsingFactoryMethod(beanName, mbd, args);
- }
- // Shortcut when re-creating the same bean...
- boolean resolved = false;
- boolean autowireNecessary = false;
- if (args == null) {
- synchronized (mbd.constructorArgumentLock) {
- if (mbd.resolvedConstructorOrFactoryMethod != null) {
- resolved = true;
- autowireNecessary = mbd.constructorArgumentsResolved;
- }
- }
- }
- if (resolved) {
- if (autowireNecessary) {
- return autowireConstructor(beanName, mbd, null, null);
- }
- else {
- return instantiateBean(beanName, mbd);
- }
- }
- // Need to determine the constructor...通过后置处理器返回构造器,然后通过autowireConstructor去筛选构造器,这种可用于配置文件中没有配置构造器参数的方式。
- Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
- if (ctors != null ||
- mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
- mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
- return autowireConstructor(beanName, mbd, ctors, args);
- }
- // No special handling: simply use no-arg constructor.
- //使用无参构造器构造
- return instantiateBean(beanName, mbd);
- }
- AbstractAutowireCapableBeanFactory.autowireConstructor
- protected BeanWrapper autowireConstructor(
- String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {
- return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
- }
- ConstructorResolver.autowireConstructor
- //beanName表示正在创建bean的名字,mbd表示正在创建bean的BeanDefinition,chosenCtors表示是程序指定的可选构造器列表,可通过后置处理器得到,explicitArgs是用户指定的构造参数
- public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
- Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
- BeanWrapperImpl bw = new BeanWrapperImpl();
- //初始化,注册类型转化器和自定义类型转化器
- this.beanFactory.initBeanWrapper(bw);
- Constructor<?> constructorToUse = null;
- ArgumentsHolder argsHolderToUse = null;
- Object[] argsToUse = null;
- if (explicitArgs != null) {
- argsToUse = explicitArgs;
- }
- else {
- //这里的操作和解析工厂方法时一样的
- Object[] argsToResolve = null;
- synchronized (mbd.constructorArgumentLock) {
- //从缓存中获取
- constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
- if (constructorToUse != null && mbd.constructorArgumentsResolved) {
- // Found a cached constructor...
- argsToUse = mbd.resolvedConstructorArguments;
- if (argsToUse == null) {
- //使用预备的集合参数
- argsToResolve = mbd.preparedConstructorArguments;
- }
- }
- }
- if (argsToResolve != null) {
- //解析预备参数集合
- argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
- }
- }
- //如果没有缓存,那么就从头开始查找
- if (constructorToUse == null) {
- // Need to resolve the constructor.
- //如果用户指定了构造器,或者装配为构造器自动装配
- boolean autowiring = (chosenCtors != null ||
- mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
- ConstructorArgumentValues resolvedValues = null;
- int minNrOfArgs;
- if (explicitArgs != null) {
- minNrOfArgs = explicitArgs.length;
- }
- else {
- ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
- resolvedValues = new ConstructorArgumentValues();
- //解析配置的参数
- minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
- }
- // Take specified constructors, if any.
- Constructor<?>[] candidates = chosenCtors;
- if (candidates == null) {
- Class<?> beanClass = mbd.getBeanClass();
- try {
- //如果没有指定构造器,那么就获取当前bean的构造器
- candidates = (mbd.isNonPublicAccessAllowed() ?
- beanClass.getDeclaredConstructors() : beanClass.getConstructors());
- }
- catch (Throwable ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Resolution of declared constructors on bean Class [" + beanClass.getName() +
- "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
- }
- }
- //进行排序,public在前,参数长的在前
- AutowireUtils.sortConstructors(candidates);
- int minTypeDiffWeight = Integer.MAX_VALUE;
- Set<Constructor<?>> ambiguousConstructors = null;
- LinkedList<UnsatisfiedDependencyException> causes = null;
- for (int i = 0; i < candidates.length; i++) {
- Constructor<?> candidate = candidates[i];
- Class<?>[] paramTypes = candidate.getParameterTypes();
- if (constructorToUse != null && argsToUse.length > paramTypes.length) {
- // Already found greedy constructor that can be satisfied ->
- // do not look any further, there are only less greedy constructors left.
- break;
- }
- if (paramTypes.length < minNrOfArgs) {
- continue;
- }
- ArgumentsHolder argsHolder;
- if (resolvedValues != null) {
- try {
- String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
- if (paramNames == null) {
- ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
- if (pnd != null) {
- paramNames = pnd.getParameterNames(candidate);
- }
- }
- argsHolder = createArgumentArray(
- beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
- }
- catch (UnsatisfiedDependencyException ex) {
- if (this.beanFactory.logger.isTraceEnabled()) {
- this.beanFactory.logger.trace(
- "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
- }
- // Swallow and try next constructor.
- if (causes == null) {
- causes = new LinkedList<UnsatisfiedDependencyException>();
- }
- causes.add(ex);
- continue;
- }
- }
- else {
- // Explicit arguments given -> arguments length must match exactly.
- if (paramTypes.length != explicitArgs.length) {
- continue;
- }
- argsHolder = new ArgumentsHolder(explicitArgs);
- }
- //根据一些宽松或者严格模式去寻找更适合的构造器
- int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
- argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
- // Choose this constructor if it represents the closest match.
- if (typeDiffWeight < minTypeDiffWeight) {
- constructorToUse = candidate;
- argsHolderToUse = argsHolder;
- argsToUse = argsHolder.arguments;
- minTypeDiffWeight = typeDiffWeight;
- ambiguousConstructors = null;
- }
- else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
- if (ambiguousConstructors == null) {
- ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
- ambiguousConstructors.add(constructorToUse);
- }
- //存储存在歧义的构造器
- ambiguousConstructors.add(candidate);
- }
- }
- if (constructorToUse == null) {
- if (causes != null) {
- UnsatisfiedDependencyException ex = causes.removeLast();
- for (Exception cause : causes) {
- this.beanFactory.onSuppressedException(cause);
- }
- throw ex;
- }
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Could not resolve matching constructor " +
- "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
- }
- else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Ambiguous constructor matches found in bean '" + beanName + "' " +
- "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
- ambiguousConstructors);
- }
- if (explicitArgs == null) {
- argsHolderToUse.storeCache(mbd, constructorToUse);
- }
- }
- try {
- Object beanInstance;
- if (System.getSecurityManager() != null) {
- final Constructor<?> ctorToUse = constructorToUse;
- final Object[] argumentsToUse = argsToUse;
- beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- return beanFactory.getInstantiationStrategy().instantiate(
- mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
- }
- }, beanFactory.getAccessControlContext());
- }
- else {
- //构造对应的bean实例
- beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
- mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
- }
- bw.setWrappedInstance(beanInstance);
- return bw;
- }
- catch (Throwable ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Bean instantiation via constructor failed", ex);
- }
- }
bean的创建(五)第四部分 bean构造器的查找的更多相关文章
- Spring 源码(17)Spring Bean的创建过程(8)Bean的初始化
知识回顾 Bean的创建过程会经历getBean,doGetBean,createBean,doCreateBean,然后Bean的创建又会经历实例化,属性填充,初始化. 在实例化createInst ...
- 0003 - 基于xml的Spring Bean 的创建过程
一.目录 前言 创建 Bean 容器 加载 Bean 定义 创建 Bean Spring Bean 创建过程中的设计模式 总结 二.前言 2.1 Spring 使用配置 ApplicationCont ...
- Solon 开发,四、Bean 扫描的三种方式
Solon 开发 一.注入或手动获取配置 二.注入或手动获取Bean 三.构建一个Bean的三种方式 四.Bean 扫描的三种方式 五.切面与环绕拦截 六.提取Bean的函数进行定制开发 七.自定义注 ...
- Spring 源码(11)Spring Bean 的创建过程(2)
Spring Bean 的创建过程介绍了FactoryBean 的创建方式,那么接下来介绍不是FactoryBean的创建方式,在创建过程中,又会分为单例的Bean的创建,原型类型的Bean的创建等. ...
- Spring源码学习-容器BeanFactory(五) Bean的创建-探寻Bean的新生之路
写在前面 上面四篇文章讲了Spring是如何将配置文件一步一步转化为BeanDefinition的整个流程,下面就到了正式创建Bean对象实例的环节了,我们一起继续学习吧. 2.初始化Bean对象实例 ...
- bean的创建(五)第二部分 寻找bean的工厂方法实例化
instanceWrapper = createBeanInstance(beanName, mbd, args); AbstractAutowireCapableBeanFactory.create ...
- bean的创建(五)第一部分
AbstractBeanFactory.doGetBean protected <T> T doGetBean( final String name, final Class<T&g ...
- bean的创建(五)第五部分 属性填充
AbstractAutowireCapableBeanFactory.populateBean protected void populateBean(String beanName, RootBea ...
- Spring学习笔记之 Spring IOC容器(一)之 实例化容器,创建JavaBean对象,控制Bean实例化,setter方式注入,依赖属性的注入,自动装配功能实现自动属性注入
本节主要内容: 1.实例化Spring容器示例 2.利用Spring容器创建JavaBean对象 3.如何控制Bean实例化 4.利用Spring实现bean属性sett ...
- Spring源码分析之Bean的创建过程详解
前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...
随机推荐
- 30441数据定义语言DDL
数据定义:指对数据库对象的定义.删除和修改操作. 数据库对象主要包括数据表.视图.索引等. 数据定义功能通过CREATE.ALTER.DROP语句来完成. 按照操作对象分类来介绍数据定义的SQL语法. ...
- abp(net core)+easyui+efcore仓储系统——展现层实现增删改查之控制器(六)
abp(net core)+easyui+efcore仓储系统目录 abp(net core)+easyui+efcore仓储系统——ABP总体介绍(一) abp(net core)+easyui+e ...
- ZooKeeper学习第四期---构建ZooKeeper应用(转)
转载来源:https://www.cnblogs.com/sunddenly/p/4064992.html 一.配置服务 配置服务是分布式应用所需要的基本服务之一,它使集群中的机器可以共享配置信息中那 ...
- 02-MySQL的安装和管理
# mysql的安装和基本管理 # 01 数据库管理软件分类 ''' 分两大类: 关系型:如sqllite,db2,oracle,access,sql server,MySQL,注意:sql语句通用 ...
- Spring Bean的3种装配方式
Bean常用的装配方式有3种: 基于xml的装配 基于Annotation(注解)的装配 基于Java类的装配 基于xml的装配 在xml文件中配置Bean. 如果依赖很多,xml配置文件会很臃肿,后 ...
- HBase 学习之路(二)—— HBase系统架构及数据结构
一.基本概念 一个典型的Hbase Table 表如下: 1.1 Row Key (行键) Row Key是用来检索记录的主键.想要访问HBase Table中的数据,只有以下三种方式: 通过指定的R ...
- java编程思想之面向对象
面向对象和面向过程 面向对象(Object Oriented),简称OO,是软件开发方法的一种,我们都知道java是基于面向对象开发的,但是说到面向对象,我们不得不提一提面向过程开发,面向过程,又称结 ...
- js避坑历险记
代码改变世界,世界改变码农,码农改变代码! 我就是我,我就是一个码农的武林. 前方JS巨坑出没,请注意集中力! 巨坑1:js精度问题 前段时间去一家物流公司面试,做了一个js题,印象尤为深刻: var ...
- .NET Core IdentityServer4实战 第六章-Consent授权页
在identityServer4中登陆页面只要是成功了,就会注册一个Cookie在服务器资源上,像现在大部分的网站第三方授权,都是经过一个页面,然后选需要的功能,IdentityServer4也给我们 ...
- spring boot 2.0 thymeleaf调试时正常,打包后运行报错. 找不到模板文件.
使用th:fragment 定义模板 使用 th:replace 来添加模板到需要的地方. 使用时发现一个非常奇怪的问题. 本机idea 调试环境一切正常, 但是打成jar包以后报错,提示找不到对 ...