您现在的位置是:主页 > news > 晒豆网站建设/sem竞价托管费用
晒豆网站建设/sem竞价托管费用
admin2025/6/10 12:24:43【news】
简介晒豆网站建设,sem竞价托管费用,保定高端模板建站,微信网页制作网站Mybatis源码体系介绍和配置文件解析源码剖析 Mybatis和传统JDBC的优势 Mybatis MyBatis是一个持久层的ORM框架,使用简单,学习成本较低。可以执行自己手写的 SQL语句,比较灵活。但是MyBatis的自动化程度不高,移植性也不高&#…
Mybatis源码体系介绍和配置文件解析源码剖析
Mybatis和传统JDBC的优势
Mybatis
- MyBatis是一个持久层的ORM框架,使用简单,学习成本较低。可以执行自己手写的
SQL语句,比较灵活。但是MyBatis的自动化程度不高,移植性也不高,有时从一个数
据库迁移到另外-个数据库的时候需要自己修改配置,所以称只为半自动ORM框架
JDBC
四大核心对象
- DriverMananger
- Connection
- PerparedStatement
- ResultSet
存在的问题
- 数据库连接创建,释放频繁造成西戎资源的浪费,从而影响系统性能,使用数据库连
接池可以解决问题。 - sq|语句在代码中硬编码,造成代码的不已维护,实际应用中sqI的变化可能较大,
sql代码和java代码没有分离开来维护不方便。 - 使用preparedStatement向有占位符传递参数存在硬编码问题因为sql中的where
子句的条件不确定,同样是修改不方便 - 对结果集中解析存在硬编码问题,sql的变化导致解析代码的变化,系统维护不方
便。
图说Mybatis的整体体系结构
MyBatis的主要的核心部件
- Configuration 初始化基础配置,比如MyBatis的别名等,一些重要的类型对象,如,插件,映射器,ObjectFactory和typeHandler对象,MyBatis所有的配置信息都维持在Configuration对象之中
SqlSessionFactory SqlSession工厂 - SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能
- Executor MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
- StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。
- ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所需要的参数,
- ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合;
- TypeHandler 负责java数据类型和jdbc数据类型之间的映射和转换
- MappedStatement MappedStatement维护了一条<select|update|delete|insert>节点的封装,
- SqlSource 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
- BoundSql 表示动态生成的SQL语句以及相应的参数信息
Mybatis整体体系图
Mybatis的三层功能架构
- API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用详
完成具体的数据处理。 - 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用
作。 - 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的
最基础的组件。为上层的数据处理层提供最基础的支撑。
Mybatis配置文件解析
XMLConfigBuilder
- 用来解析mybatis-config.xml这个文件,将信息设置到Configuration对象里面
插件解析
- 解析mybatis-config.xml中的plugins标签下的内容,获得interceptor中的内容,通过反射实例化成Interceptor,添加到configuration属性中的interceptorChain中,调用的话通过责任链依次调用
XMLMapperBuilder
- 用来解析xxxx.xml映射文件
XMLStatementBuilder
- 解析我们的增删查改节点
- 每一个sql映射成一个MapperStateMent
Mybatis的数据操作过程源码解析
Mybatis插件(Plugin)的执行原理
- 为四大对象做增强
DefaultSqlSessionFactory#openSessionFromConnection
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {try {boolean autoCommit;try {autoCommit = connection.getAutoCommit();} catch (SQLException e) {// Failover to true, as most poor drivers// or databases won't support transactionsautoCommit = true;}final Environment environment = configuration.getEnvironment();//获取事务工厂final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);final Transaction tx = transactionFactory.newTransaction(connection);// 创建一个sql执行器大对象final Executor executor = configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor, autoCommit);} catch (Exception e) {throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);} finally {ErrorContext.instance().reset();}}
org.apache.ibatis.session.Configuration#newExecutor()
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {//判断传进来的executorType是不是为空executorType = executorType == null ? defaultExecutorType : executorType;executorType = executorType == null ? ExecutorType.SIMPLE : executorType;Executor executor;/*** 判断执行器的类型* *///批量的执行器if (ExecutorType.BATCH == executorType) {executor = new BatchExecutor(this, transaction);} else if (ExecutorType.REUSE == executorType) {//可重复使用的执行器executor = new ReuseExecutor(this, transaction);} else {//简单的sql执行器对象executor = new SimpleExecutor(this, transaction);}//判断是否开启缓存if (cacheEnabled) {//包装成CachingExecutorexecutor = new CachingExecutor(executor);}//调用所有的拦截器对象plugin方法executor = (Executor) interceptorChain.pluginAll(executor);return executor;}//循环调用重新的方法
public Object pluginAll(Object target) {for (Interceptor interceptor : interceptors) {target = interceptor.plugin(target);}return target;}//自定的interceptor重写了plugin方法
@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}// 创建动态代理
public static Object wrap(Object target, Interceptor interceptor) {// 获得interceptor配置的@Signature的typeMap<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);//当前代理类型Class<?> type = target.getClass();//根据当前的代理类型和@signature指定的type进行配对,配对成功则可以代理Class<?>[] interfaces = getAllInterfaces(type, signatureMap);if (interfaces.length > 0) {return Proxy.newProxyInstance(type.getClassLoader(),interfaces,new Plugin(target, interceptor, signatureMap));}return target;}
当调用里面的某个方法时
DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
@Overridepublic <T> T selectOne(String statement, Object parameter) {// Popular vote was to return null on 0 results and throw exception on too many.List<T> list = this.selectList(statement, parameter);if (list.size() == 1) {return list.get(0);} else if (list.size() > 1) {throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());} else {return null;}}private <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {try {//第一步:通过我们的statement去我们的全局配置类中获取MappedStatementMappedStatement ms = configuration.getMappedStatement(statement);//最终还是会有execuotor执行某个方法,Plugin里面,因为为executor创建了动态代理return executor.query(ms, wrapCollection(parameter), rowBounds, handler);} catch (Exception e) {throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);} finally {ErrorContext.instance().reset();}}private Object wrapCollection(final Object object) {return ParamNameResolver.wrapToMapIfCollection(object, null);}public static Object wrapToMapIfCollection(Object object, String actualParamName) {//如果我们的参数类型是Collectionif (object instanceof Collection) {ParamMap<Object> map = new ParamMap<>();// 把他key为collection存放到map中map.put("collection", object);//如果我们的参数类型是listif (object instanceof List) {map.put("list", object);}//如果传入的有别名的话,也添加到map里面//这也是为什么如果如果参数是集合或者数据可以使用list或者array的原因Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));return map;} else if (object != null && object.getClass().isArray()) {//包装arrayParamMap<Object> map = new ParamMap<>();map.put("array", object);Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));return map;}return object;}//创建了动态代理,走到了plugin里面的invoke方法
@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {//判断方法是否符合Set<Method> methods = signatureMap.get(method.getDeclaringClass());if (methods != null && methods.contains(method)) {`return interceptor.intercept(new Invocation(target, method, args));}return method.invoke(target, args);} catch (Exception e) {throw ExceptionUtil.unwrapThrowable(e);}}
org.apache.ibatis.plugin.Plugin#invoke
@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {//拿到自定义拦截器中的注解中拦截的方法Set<Method> methods = signatureMap.get(method.getDeclaringClass());//判断是否包含if (methods != null && methods.contains(method)) {//走到自定义拦截器中的重写的intercept方法,已经把目标对象,方法名,以及参数封装到了Invocation并且传给下一个return interceptor.intercept(new Invocation(target, method, args));}//如果不包含则直接调用return method.invoke(target, args);} catch (Exception e) {throw ExceptionUtil.unwrapThrowable(e);}}//自定义的Interceptor中的intercept方法
@Overridepublic Object intercept(Invocation invocation) throws Throwable {System.out.println("代理");Object[] args = invocation.getArgs();MappedStatement ms = (MappedStatement) args[0];return invocation.proceed();}
CachingExecutor#query()
@Overridepublic <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {//通过参数解析我们的sql详细信息BoundSql boundSql = ms.getBoundSql(parameterObject);//创建缓存的keyCacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);}@Overridepublic <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)throws SQLException {// 判断是否开启了二级缓存Cache cache = ms.getCache();if (cache != null) {//是否需要刷新缓存flushCacheIfRequired(ms);if (ms.isUseCache() && resultHandler == null) {ensureNoOutParams(ms, boundSql);@SuppressWarnings("unchecked")//去二级缓存中获取List<E> list = (List<E>) tcm.getObject(cache, key);if (list == null) {//二级缓存中没有查询数据库list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);//存储到缓存tcm.putObject(cache, key, list); // issue #578 and #116}return list;}}return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);}BaseExecutor#query()
@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());if (closed) {throw new ExecutorException("Executor was closed.");}if (queryStack == 0 && ms.isFlushCacheRequired()) {clearLocalCache();}List<E> list;try {//从一级缓存中,获取查询结果queryStack++;list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;if (list != null) {handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);} else {//获取不到,则从数据库中查询list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);}} finally {queryStack--;}if (queryStack == 0) {for (DeferredLoad deferredLoad : deferredLoads) {deferredLoad.load();}// issue #601deferredLoads.clear();if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {// issue #482clearLocalCache();}}return list;}SimpleExecutor#doQuery
@Overridepublic <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {Statement stmt = null;try {//拿到configuration对象Configuration configuration = ms.getConfiguration();//new一个StatementHandlerStatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);stmt = prepareStatement(handler, ms.getStatementLog());return handler.query(stmt, resultHandler);} finally {closeStatement(stmt);}}private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {Statement stmt;//拿到connection对象Connection connection = getConnection(statementLog);stmt = handler.prepare(connection, transaction.getTimeout());handler.parameterize(stmt);return stmt;}public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {//默认为为PrepareddStatementHandlerStatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);return statementHandler;}//PrepareddStatementHandler的父类的构造方法
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {this.configuration = mappedStatement.getConfiguration();this.executor = executor;this.mappedStatement = mappedStatement;this.rowBounds = rowBounds;this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();this.objectFactory = configuration.getObjectFactory();if (boundSql == null) { // issue #435, get the key before calculating the statementgenerateKeys(parameterObject);boundSql = mappedStatement.getBoundSql(parameterObject);}this.boundSql = boundSql;//创建parameterHandler和resultSetHandlerthis.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);}//创建ParameterHandler的时候会创建动态代理
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);return parameterHandler;}
MappedStatement#getBoundSql
public BoundSql getBoundSql(Object parameterObject) {BoundSql boundSql = sqlSource.getBoundSql(parameterObject);List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();if (parameterMappings == null || parameterMappings.isEmpty()) {boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);}// check for nested result maps in parameter mappings (issue #30)for (ParameterMapping pm : boundSql.getParameterMappings()) {String rmId = pm.getResultMapId();if (rmId != null) {ResultMap rm = configuration.getResultMap(rmId);if (rm != null) {hasNestedResultMaps |= rm.hasNestedResultMaps();}}}return boundSql;}@Overridepublic BoundSql getBoundSql(Object parameterObject) {DynamicContext context = new DynamicContext(configuration, parameterObject);//1.递归责任链,处理一个个SqlNode,编译出一个完整sql//首先来到MixedSqlNode,获得所有的SqlNode,循环所有的SqlNode//如果是StatisTextSqlNode,添加到DynamicContext的sqlBuilder字段上//WhereSqlNode里面还包含其他的比如说if,foreachrootSqlNode.apply(context);SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);// 2,接下来处理sql中的#{...}// 拿到#{}中的内容,封装为parameterMapper,替换成?Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());BoundSql boundSql = sqlSource.getBoundSql(parameterObject);context.getBindings().forEach(boundSql::setAdditionalParameter);return boundSql;}@Overridepublic boolean apply(DynamicContext context) {FilteredDynamicContext filteredDynamicContext = new FilteredDynamicContext(context);//递归trim(where\set)中的内容 boolean result = contents.apply(filteredDynamicContext);filteredDynamicContext.applyAll();return result;}public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);String sql;if (configuration.isShrinkWhitespacesInSql()) {sql = parser.parse(removeExtraWhitespaces(originalSql));} else {// 替换Sql中的#{}替换成问好,并且会顺便拿到#{}中的参数名称解析成ParameterMapperingsql = parser.parse(originalSql);}return new StaticSqlSource(configuration, sql, handler.getParameterMappings());}
最终得到要执行的sql
Mybatis缓存(Cache)的执行原理
Mybatis整合Spring的全过程源码解析
org.apache.ibatis.binding.MapperRegistry#getMapper
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {//直接去缓存knownMappers中通过Mapper的calss类型去找我们的mapperProxyFactoryfinal MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);if (mapperProxyFactory == null) {throw new BindingException("Type " + type + " is not known to the MapperRegistry.");}try {return mapperProxyFactory.newInstance(sqlSession);} catch (Exception e) {throw new BindingException("Error getting mapper instance. Cause: " + e, e);}}public T newInstance(SqlSession sqlSession) {final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);return newInstance(mapperProxy);}//最终创建接口的JDK动态代理
protected T newInstance(MapperProxy<T> mapperProxy) {return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {//判断方法是不是object类定义的方法,如果是直接通过反射调用if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);} else {return cachedInvoker(method).invoke(proxy, method, args, sqlSession);}} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}}private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {try {return MapUtil.computeIfAbsent(methodCache, method, m -> {if (m.isDefault()) {try {if (privateLookupInMethod == null) {return new DefaultMethodInvoker(getMethodHandleJava8(method));} else {return new DefaultMethodInvoker(getMethodHandleJava9(method));}} catch (IllegalAccessException | InstantiationException | InvocationTargetException| NoSuchMethodException e) {throw new RuntimeException(e);}} else {//返回PlainMethodInvoker,并且把我们的方法对象封装成一个MapperMethod对象return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));}});} catch (RuntimeException re) {Throwable cause = re.getCause();throw cause == null ? re : cause;}}public Object execute(SqlSession sqlSession, Object[] args) {Object result;// 判断我们执行sql命令的类型switch (command.getType()) {case INSERT: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.insert(command.getName(), param));break;}case UPDATE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.update(command.getName(), param));break;}case DELETE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.delete(command.getName(), param));break;}case SELECT:if (method.returnsVoid() && method.hasResultHandler()) {executeWithResultHandler(sqlSession, args);result = null;} else if (method.returnsMany()) {result = executeForMany(sqlSession, args);} else if (method.returnsMap()) {result = executeForMap(sqlSession, args);} else if (method.returnsCursor()) {result = executeForCursor(sqlSession, args);} else {Object param = method.convertArgsToSqlCommandParam(args);result = sqlSession.selectOne(command.getName(), param);if (method.returnsOptional()&& (result == null || !method.getReturnType().equals(result.getClass()))) {result = Optional.ofNullable(result);}}break;case FLUSH:result = sqlSession.flushStatements();break;default:throw new BindingException("Unknown execution method for: " + command.getName());}if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {throw new BindingException("Mapper method '" + command.getName()+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");}return result;}
Spring管理Mapper代理
- 一个接口不能被注册成BeanDefinition
其他mybatis重要类的分析
SqlSqlSessionManager
-
既实现了SqlSessionFactory,也实现了SqlSession,具备生产SqlSession的能力,也具备SqlSession的能力,SqlSession的作用是执行具体的Sql语句.SqlSessionFactory和SqlSession都是两个Interface.也就是说他是两个功能集合的封装
-
SqlSessionManager内部有三个成员变量
- 变量sqlSessionFactory具体实现SqlSessionFactory的功能,SqlSessionManager没有在做额外的处理,所以本质上,使用DefaultSqlSessionFactory和使用SqlSessionManager调用相同的方法,他们的返回结果是一模一样的,没有区别
- 重点在sqlSessionProxy,首先它是SqlSessionManager的成员变量,去实现SqlSession的功能,SqlSessionManager同样对相关方法也没有做额外处理;其次,他有特殊的赋值方法,先看SqlSessionManager唯一的构造方法
- sqlSessionFactory作为入参,直接赋值给成员变量,而sqlSessionProxy的赋值,看到了很熟悉的动态代理,动态代理的三个入参:第一个是appClassLoader,第二个是需要被代理的Class,自然是SqlSession,第三个是代理拦截器,new 了一个SqlSessionInterceptor,这个是SqlSessionManager的内部类
@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//如果localSqlSession中的sqlSession不为空,则直接进行反射//如果localSqlSession中的sqlSession为空,则使用openSession()生产一个final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get();if (sqlSession != null) {try {return method.invoke(sqlSession, args);} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}} else {try (SqlSession autoSqlSession = openSession()) {try {final Object result = method.invoke(autoSqlSession, args);autoSqlSession.commit();return result;} catch (Throwable t) {autoSqlSession.rollback();throw ExceptionUtil.unwrapThrowable(t);}}}}}
- 在调用SqlSession时,触发动态代理,先去成员变量localSqlSession变量中拿,也就是上面说的第三个变量,第一次拿肯定是空的,于是通过openSession()方法获得一个SqlSession,然后使用这个SqlSession去完成其他事情,所以成员变量的任何方法调用都是对localSqlSession的反射
- 但是如果每次都要调用openSession(),是一种资源浪费,其次SqlSessionManager作为线程安全类,这样也是一种不正确的使用方法,所以SqlSessionManager也提供了很多设置localSqlSession的方法
- SqlSessionManager主要是使用了ThreadLocal保证线程安全,每个线程独享一份SqlSession,所以保证SqlSession的方法都是线程安全的,但是非SqlSession的方法,并不是线程安全的
FactoryMethod使用和原理
AbstractAutowireCapableBeanFactory#createBeanInstance
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());}Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}//如果FactoryMethodName不为空if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}.........}//实例化一个ConstructorResolver对象并调用它的instantiateUsingFactoryMethod函数
protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);}public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {BeanWrapperImpl bw = new BeanWrapperImpl();this.beanFactory.initBeanWrapper(bw);Object factoryBean;Class<?> factoryClass;boolean isStatic;//获得factory-bean属性String factoryBeanName = mbd.getFactoryBeanName();if (factoryBeanName != null) {if (factoryBeanName.equals(beanName)) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,"factory-bean reference points back to the same bean definition");}//根据factoryBeanName创建BeanfactoryBean = this.beanFactory.getBean(factoryBeanName);if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {throw new ImplicitlyAppearedSingletonException();}factoryClass = factoryBean.getClass();isStatic = false;}else {// It's a static factory method on the bean class.if (!mbd.hasBeanClass()) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,"bean definition declares neither a bean class nor a factory-bean reference");}factoryBean = null;//获取bean本身定义的class属性factoryClass = mbd.getBeanClass();isStatic = true;}Method factoryMethodToUse = null;ArgumentsHolder argsHolderToUse = null;Object[] argsToUse = null;if (explicitArgs != null) {argsToUse = explicitArgs;}else {Object[] argsToResolve = null;synchronized (mbd.constructorArgumentLock) {factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {// Found a cached factory method...argsToUse = mbd.resolvedConstructorArguments;if (argsToUse == null) {argsToResolve = mbd.preparedConstructorArguments;}}}if (argsToResolve != null) {argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);}}if (factoryMethodToUse == null || argsToUse == null) {// Need to determine the factory method...// Try all methods with this name to see if they match the given arguments.factoryClass = ClassUtils.getUserClass(factoryClass);List<Method> candidateList = null;if (mbd.isFactoryMethodUnique) {if (factoryMethodToUse == null) {factoryMethodToUse = mbd.getResolvedFactoryMethod();}if (factoryMethodToUse != null) {candidateList = Collections.singletonList(factoryMethodToUse);}}if (candidateList == null) {candidateList = new ArrayList<>();Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);for (Method candidate : rawCandidates) {if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {candidateList.add(candidate);}}}if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {Method uniqueCandidate = candidateList.get(0);if (uniqueCandidate.getParameterCount() == 0) {mbd.factoryMethodToIntrospect = uniqueCandidate;synchronized (mbd.constructorArgumentLock) {mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;mbd.constructorArgumentsResolved = true;mbd.resolvedConstructorArguments = EMPTY_ARGS;}bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));return bw;}}Method[] candidates = candidateList.toArray(new Method[0]);AutowireUtils.sortFactoryMethods(candidates);ConstructorArgumentValues resolvedValues = null;boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);int minTypeDiffWeight = Integer.MAX_VALUE;Set<Method> ambiguousFactoryMethods = null;int minNrOfArgs;if (explicitArgs != null) {minNrOfArgs = explicitArgs.length;}else {// We don't have arguments passed in programmatically, so we need to resolve the// arguments specified in the constructor arguments held in the bean definition.if (mbd.hasConstructorArgumentValues()) {ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();resolvedValues = new ConstructorArgumentValues();minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);}else {minNrOfArgs = 0;}}LinkedList<UnsatisfiedDependencyException> causes = null;for (Method candidate : candidates) {Class<?>[] paramTypes = candidate.getParameterTypes();if (paramTypes.length >= minNrOfArgs) {ArgumentsHolder argsHolder;if (explicitArgs != null) {// Explicit arguments given -> arguments length must match exactly.if (paramTypes.length != explicitArgs.length) {continue;}argsHolder = new ArgumentsHolder(explicitArgs);}else {// Resolved constructor arguments: type conversion and/or autowiring necessary.try {String[] paramNames = null;ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();if (pnd != null) {paramNames = pnd.getParameterNames(candidate);}argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,paramTypes, paramNames, candidate, autowiring, candidates.length == 1);}catch (UnsatisfiedDependencyException ex) {if (logger.isTraceEnabled()) {logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);}// Swallow and try next overloaded factory method.if (causes == null) {causes = new LinkedList<>();}causes.add(ex);continue;}}int typeDiffWeight = (mbd.isLenientConstructorResolution() ?argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));// Choose this factory method if it represents the closest match.if (typeDiffWeight < minTypeDiffWeight) {factoryMethodToUse = candidate;argsHolderToUse = argsHolder;argsToUse = argsHolder.arguments;minTypeDiffWeight = typeDiffWeight;ambiguousFactoryMethods = null;}// Find out about ambiguity: In case of the same type difference weight// for methods with the same number of parameters, collect such candidates// and eventually raise an ambiguity exception.// However, only perform that check in non-lenient constructor resolution mode,// and explicitly ignore overridden methods (with the same parameter signature).else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&!mbd.isLenientConstructorResolution() &¶mTypes.length == factoryMethodToUse.getParameterCount() &&!Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {if (ambiguousFactoryMethods == null) {ambiguousFactoryMethods = new LinkedHashSet<>();ambiguousFactoryMethods.add(factoryMethodToUse);}ambiguousFactoryMethods.add(candidate);}}}if (factoryMethodToUse == null || argsToUse == null) {if (causes != null) {UnsatisfiedDependencyException ex = causes.removeLast();for (Exception cause : causes) {this.beanFactory.onSuppressedException(cause);}throw ex;}List<String> argTypes = new ArrayList<>(minNrOfArgs);if (explicitArgs != null) {for (Object arg : explicitArgs) {argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");}}else if (resolvedValues != null) {Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());valueHolders.addAll(resolvedValues.getGenericArgumentValues());for (ValueHolder value : valueHolders) {String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));argTypes.add(argType);}}String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);throw new BeanCreationException(mbd.getResourceDescription(), beanName,"No matching factory method found: " +(mbd.getFactoryBeanName() != null ?"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +"Check that a method with the specified name " +(minNrOfArgs > 0 ? "and arguments " : "") +"exists and that it is " +(isStatic ? "static" : "non-static") + ".");}else if (void.class == factoryMethodToUse.getReturnType()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Invalid factory method '" + mbd.getFactoryMethodName() +"': needs to have a non-void return type!");}else if (ambiguousFactoryMethods != null) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Ambiguous factory method matches found in bean '" + beanName + "' " +"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +ambiguousFactoryMethods);}if (explicitArgs == null && argsHolderToUse != null) {mbd.factoryMethodToIntrospect = factoryMethodToUse;argsHolderToUse.storeCache(mbd, factoryMethodToUse);}}bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));return bw;}1.根据是否是静态工厂获取候选factoryMethodToUse。2.遍历候选函数获取构造函数放入argsToUse数组中3.调用instantiate函数放入BeanWrapper的wrappedObject和rootObject中。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);}}@Overridepublic 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);}Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();try {currentlyInvokedFactoryMethod.set(factoryMethod);Object result = factoryMethod.invoke(factoryBean, args );if (result == null) {result = new NullBean();}return result;}finally {if (priorInvokedFactoryMethod != null) {currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);}else {currentlyInvokedFactoryMethod.remove();}}}}通过反射调用了factoryMethod方法返回了Bean实例
AbstractBeanFactory#getObjectForBeanInstance
- FactoryBean的getObject()只有在调用某一个Bean的时候才会起作用
org.springframework.beans.factory.support.
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {// Don't let calling code try to dereference the factory if the bean isn't a factory.if (BeanFactoryUtils.isFactoryDereference(name)) {if (beanInstance instanceof NullBean) {return beanInstance;}if (!(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());}if (mbd != null) {mbd.isFactoryBean = true;}return beanInstance;}// Now we have the bean instance, which may be a normal bean or a FactoryBean.// If it's a FactoryBean, we use it to create a bean instance, unless the// caller actually wants a reference to the factory.if (!(beanInstance instanceof FactoryBean)) {return beanInstance;}Object object = null;if (mbd != null) {mbd.isFactoryBean = true;}else {object = getCachedObjectForFactoryBean(beanName);}if (object == null) {// 转为FactoryBeanFactoryBean<?> factory = (FactoryBean<?>) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.if (mbd == null && containsBeanDefinition(beanName)) {mbd = getMergedLocalBeanDefinition(beanName);}boolean synthetic = (mbd != null && mbd.isSynthetic());object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;}FactoryBeanRegistrySupport#doGetObjectFromFactoryBeanprivate Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)throws BeanCreationException {Object object;try {if (System.getSecurityManager() != null) {AccessControlContext acc = getAccessControlContext();try {object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);}catch (PrivilegedActionException pae) {throw pae.getException();}}else {//调用factory的getObject()object = factory.getObject();}}catch (FactoryBeanNotInitializedException ex) {throw new BeanCurrentlyInCreationException(beanName, ex.toString());}catch (Throwable ex) {throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);}// Do not accept a null value for a FactoryBean that's not fully// initialized yet: Many FactoryBeans just return null then.if (object == null) {if (isSingletonCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");}object = new NullBean();}return object;}
CreationException {
Object object;try {if (System.getSecurityManager() != null) {AccessControlContext acc = getAccessControlContext();try {object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);}catch (PrivilegedActionException pae) {throw pae.getException();}}else {//调用factory的getObject()object = factory.getObject();}}catch (FactoryBeanNotInitializedException ex) {throw new BeanCurrentlyInCreationException(beanName, ex.toString());}catch (Throwable ex) {throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);}// Do not accept a null value for a FactoryBean that's not fully// initialized yet: Many FactoryBeans just return null then.if (object == null) {if (isSingletonCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");}object = new NullBean();}return object;
}