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

湖南建设网站北京装修平台网站

湖南建设网站,北京装修平台网站,南昌地宝网二手车,韩国网页设计欣赏写目录 一 CreateBean二 doCreateBean2.1 BeanWrapper2.2 缓存删除2.3 实例化Bean2.3.1 Supplier创建对象2.3.2 工厂创建对象2.3.3 构造器创建实例无参构造构造器依赖注入Setter的依赖注入autowireConstructor实例化instantiateBean 方法 2.4 Bean的前置处理 官网#xff1a;H… 写目录 一 CreateBean二 doCreateBean2.1 BeanWrapper2.2 缓存删除2.3 实例化Bean2.3.1 Supplier创建对象2.3.2 工厂创建对象2.3.3 构造器创建实例无参构造构造器依赖注入Setter的依赖注入autowireConstructor实例化instantiateBean 方法 2.4 Bean的前置处理 官网Home参考书籍Spring源码深度解析-郝佳编著-微信读书 上一节我们看到正对不同作用域Bean的加载但是Bean的核心创建我们还没有说下面我们来看看Bean的核心加载也就是CreateBean与DoCreateBean方法的核心实现 一 CreateBean AbstractAutowireCapableBeanFactory protected Object createBean(String beanName, RootBeanDefinition mbd, Nullable Object[] args) throws BeanCreationException {if (logger.isDebugEnabled()) {logger.debug(Creating instance of bean beanName );}RootBeanDefinition mbdToUse mbd;// 确保此时的 bean 已经被解析了// 如果获取的class 属性不为null则克隆该 BeanDefinition// 主要是因为该动态解析的 class 无法保存到到共享的 BeanDefinitionClass? resolvedClass resolveBeanClass(mbd, beanName);if (resolvedClass ! null !mbd.hasBeanClass() mbd.getBeanClassName() ! null) {mbdToUse new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}try {// 验证和准备覆盖方法mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, Validation of method overrides failed, ex);}try {// 给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例// AOP 的功能就是基于这个地方Object bean resolveBeforeInstantiation(beanName, mbdToUse);if (bean ! null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,BeanPostProcessor before instantiation of bean failed, ex);}try {// 执行真正创建 bean 的过程Object beanInstance doCreateBean(beanName, mbdToUse, args);if (logger.isDebugEnabled()) {logger.debug(Finished creating instance of bean beanName );}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, Unexpected exception during bean creation, ex);} } 根据设置的class属性或者根据className来解析Class这里面逻辑十分复杂但是我们可以猜想他的作用不就是通过类加载来实例化我们编写并组装成RootBeanDefinition前面我们也说过所有的Bean后续处理都是针对于RootBeanDefinition的 // 确保此时的 bean 已经被解析了// 如果获取的class 属性不为null则克隆该 BeanDefinition// 主要是因为该动态解析的 class 无法保存到到共享的 BeanDefinitionClass? resolvedClass resolveBeanClass(mbd, beanName);if (resolvedClass ! null !mbd.hasBeanClass() mbd.getBeanClassName() ! null) {mbdToUse new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}对override属性进行标记及验证lookup-method和replace-method的而这两个配置的加载其实就是将配置统一存放在BeanDefinition中的methodOverrides属性里而这个函数的操作其实也就是针对于这两个配置的 try {// 验证和准备覆盖方法mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, Validation of method overrides failed, ex);}public void prepareMethodOverrides() throws BeanDefinitionValidationException {// Check that lookup methods exists.//检测是否存在方法注入,并循环预处理方法注入// Check that lookup methods exist and determine their overloaded status.if (hasMethodOverrides()) {getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);}}protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {// 统计注入的方法个数 int count ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());if (count 0) {throw new BeanDefinitionValidationException(Invalid method override: no method with name mo.getMethodName() on class [ getBeanClassName() ]);}// 如果为1,则将注入方法标记为未重载// 注意:当有多个重载方法时,为了确定调用哪个具体的方法,Spring对重载方法的参数解析是很复杂的// 所以,如果注入方法没有被重载这里就将其标记,省去了对方法参数的解析过程,直接调用即可else if (count 1) {// Mark override as not overloaded, to avoid the overhead of arg type checking.mo.setOverloaded(false);}} 应用初始化前的后处理器解析指定bean是否存在初始化前的短路操作 在真正调用doCreate方法创建bean的实例前使用了这样一个方法resolveBeforeInstantiation (beanName, mbd)对BeanDefinigiton中的属性做些前置处理当经过前置处理后返回的结果如果不为空那么会直接略过后续的Bean的创建而直接返回结果。这一特性虽然很容易被忽略但是却起着至关重要的作用我们熟知的AOP功能就是基于这里的判断的 try {// 给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例// AOP 的功能就是基于这个地方Object bean resolveBeforeInstantiation(beanName, mbdToUse);if (bean ! null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,BeanPostProcessor before instantiation of bean failed, ex);}protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean null;// 如果没有被解析if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.// synthetic表示合成如果某些Bean式合成的那么则不会经过BeanPostProcessor的处理if (!mbd.isSynthetic() hasInstantiationAwareBeanPostProcessors()) // 确定目标类型Class? targetType determineTargetType(beanName, mbd);if (targetType ! null) {// 在实例化之前应用 Bean 后处理器bean applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean ! null) {// 初始化后应用 Bean 后处理器bean applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved (bean ! null);}return bean;}此方法中最吸引我们的无疑是两个方法applyBeanPostProcessorsBeforeInstantiation以及applyBeanPostProcessorsAfterInitialization。 两个方法实现的非常简单无非是对后处理器中的所有InstantiationAwareBeanPostProcessor类型的后处理器进行postProcessBeforeInstantiation方法和BeanPostProcessor的postProcessAfterInitialization方法的调用。后面生命周期详细讲解 参考文章spring bean扩展点后处理器 BeanPostProcessor_postprocessbeforeinstantiation 如果没有代理对象就只能走常规的路线进行 bean 的创建了该过程有 doCreateBean() 实现 二 doCreateBean 当经历过resolveBeforeInstantiation方法后程序有两个选择如果创建了代理或者说重写了InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法并在方法postProcess BeforeInstantiation中改变了bean则直接返回就可以了否则需要进行常规bean的创建。 AbstractAutowireCapableBeanFactory protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Nullable Object[] args)throws BeanCreationException {// BeanWrapper是对Bean的包装其接口中所定义的功能很简单包括设置获取被包装的对象获取被包装bean的属性描述器BeanWrapper instanceWrapper null;// 单例模型则从未完成的 FactoryBean 缓存中删除if (mbd.isSingleton()) {anceWrapper this.factoryBeanInstanceCache.remove(beanName);}// 使用合适的实例化策略来创建新的实例工厂方法、构造函数自动注入、简单初始化if (instanceWrapper null) {instanceWrapper createBeanInstance(beanName, mbd, args);}// 包装的实例对象final Object bean instanceWrapper.getWrappedInstance();// 包装的实例对象的类型Class? beanType instanceWrapper.getWrappedClass();if (beanType ! NullBean.class) {mbd.resolvedTargetType beanType;}// 检测是否有后置处理// 如果有后置处理则允许后置处理修改 BeanDefinitionsynchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {// applyMergedBeanDefinitionPostProcessors// 后置处理修改 BeanDefinitionapplyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,Post-processing of merged bean definition failed, ex);}mbd.postProcessed true;}}// 解决单例模式的循环依赖// 单例模式 运行循环依赖当前单例 bean 是否正在被创建boolean earlySingletonExposure (mbd.isSingleton() this.allowCircularReferences isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug(Eagerly caching bean beanName to allow for resolving potential circular references);}// 提前将创建的 bean 实例加入到ectFactory 中// 这里是为了后期避免循环依赖addSingletonFactory(beanName, () - getEarlyBeanReference(beanName, mbd, bean));}/** 开始初始化 bean 实例对象*/Object exposedObject bean;try {// 对 bean 进行填充将各个属性值注入其中可能存在依赖于其他 bean 的属性// 则会递归初始依赖 beanpopulateBean(beanName, mbd, instanceWrapper);// 调用初始化方法exposedObject initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, Initialization of bean failed, ex);}}/*** 循环依赖处理*/if (earlySingletonExposure) {// 获取 earlySingletonReferenceObject earlySingletonReference getSingleton(beanName, false);// 只有在存在循环依赖的情况下earlySingletonReference 才不会为空if (earlySingletonReference ! null) {// 如果 exposedObject 没有在初始化方法中被改变也就是没有被增强if (exposedObject bean) {exposedObject earlySingletonReference;}// 处理依赖else if (!this.allowRawInjectionDespiteWrapping hasDependentBean(beanName)) {String[] dependentBeans getDependentBeans(beanName);SetString actualDependentBeans new LinkedHashSet(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,Bean with name beanName has been injected into other beans [ StringUtils.collectionToCommaDelimitedString(actualDependentBeans) ] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using getBeanNamesOfType with the allowEagerInit flag turned off, for example.);}}}}try {// 注册 beanregisterDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, Invalid destruction signature, ex);}return exposedObject;} 我们来总结一下上面函数的大体步骤 如果是单例则需要首先清除缓存实例化bean将BeanDefinition转换为BeanWrapperMergedBeanDefinitionPostProcessor的应用依赖处理属性填充将所有属性填充至bean的实例中循环依赖检查注册DisposableBean完成创建并返回 我们依次来看看呗 2.1 BeanWrapper 在详细介绍之前我们先了解BeanWrapper这个类的作用 BeanWrapper是对Bean的包装其接口中所定义的功能很简单包括设置获取被包装的对象获取被包装bean的属性描述器由于BeanWrapper接口是PropertyAccessor的子接口因此其也可以设置以及访问被包装对象的属性值。 BeanWrapper大部分情况下是在spring ioc内部进行使用通过BeanWrapper,spring ioc容器可以用统一的方式来访问bean的属性。用户很少需要直接使用BeanWrapper进行编程。 2.2 缓存删除 // BeanWrapper是对Bean的包装其接口中所定义的功能很简单包括设置获取被包装的对象获取被包装bean的属性描述器BeanWrapper instanceWrapper null;// 单例模型则从未完成的 FactoryBean 缓存中删除if (mbd.isSingleton()) {anceWrapper this.factoryBeanInstanceCache.remove(beanName);}2.3 实例化Bean 参考博客Spring IoC 依赖注入四构造器或工厂注入 // 使用合适的实例化策略来创建新的实例工厂方法、Spring IoC 依赖注入四构造器或工厂注入 - binarylei - 博客园构造函数自动注入、简单初始化if (instanceWrapper null) {instanceWrapper createBeanInstance(beanName, mbd, args);}AbstractAutowireCapableBeanFactory protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Nullable Object[] args) {// 1.1 确保此时beanClassName已经加载当然注解驱动时不会设置beanClassName属性Class? beanClass resolveBeanClass(mbd, beanName);// 1.2 校验beanClass允许访问if (beanClass ! null !Modifier.isPublic(beanClass.getModifiers()) !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException();}// 2. Supplier创建对象Supplier? instanceSupplier mbd.getInstanceSupplier();if (instanceSupplier ! null) {return obtainFromSupplier(instanceSupplier, beanName);}// 工厂方法实例化 // 3. 工厂方法实例化包括实例化工厂和静态工厂if (mbd.getFactoryMethodName() ! null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}// 构造器实例化 // 4. 快速实例化对象所谓的快速实例化实际上是说使用缓存boolean resolved false;boolean autowireNecessary false;// 4.1 args: 外部化参数只能当无外部参数时才使用缓存。不推荐使用外部化参数if (args null) {synchronized (mbd.constructorArgumentLock) {// 4.2 是否使用缓存其中autowireNecessary表示是否使用有参构造器// 无参时肯定不会解析为false。有参时会解析为trueif (mbd.resolvedConstructorOrFactoryMethod ! null) {resolved true;autowireNecessary mbd.constructorArgumentsResolved;}}}// 4.3 使用缓存其中autowireNecessary表示是否使用有参构造器if (resolved) {if (autowireNecessary) {// 4.4 有参构造器实例化return autowireConstructor(beanName, mbd, null, null);} else {// 4.5 无参构造器实例化return instantiateBean(beanName, mbd);}}// 5. 到此只能老老实实的解析当然解析后会将解析后的构造器或参数缓存起来// 5.1 是否指定了构造器ibp#determineCandidateConstructorsConstructor?[] ctors determineConstructorsFromBeanPostProcessors(beanClass, beanName);// 5.2 构造器实例化if (ctors ! null || mbd.getResolvedAutowireMode() AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}// 5.3 不用管默认都是 null。ctors mbd.getPreferredConstructors();if (ctors ! null) {return autowireConstructor(beanName, mbd, ctors, null);}// 5.4 无参构造器实例化return instantiateBean(beanName, mbd); } 说明 createBeanInstance 方法在 bd.beanClass 校验后进行对象实例化而 Supplier 实例化比较简单工厂方法实例化又全部委托给了 instantiateUsingFactoryMethod 方法基本上主要的功能就是判断如何使用构造器实例化对象。 判断能否使用缓存快速实例化对象。使用缓存实例化有两个条件 外部化参数为 null。Spring 中获取对象时允许使用外部化参数 args 覆盖配置参数 bd.args。此时缓存的构造器和参数全部失效。虽然 Spring 提供了外部化参数 args但不推荐使用 getBean(beanName, args) 。缓存命中也就是构造器和参数已经解析完成。如果无参则不会解析参数此时 bd.constructorArgumentsResolvedfalse而有参则为 true。也就是可以使用该变量来判断是否使用有参构造器。 判断使用有参还是无参构造器实例化对象。使用有参构造器实例化对象有以下条件 指定构造器。ibp#determineCandidateConstructors 后置处理器可以指定实例化的构造器 ctors。AutowiredAnnotationBeanPostProcessor 会指定实例化的构造器。指定注入模式为构造器自动注入模式。目前这种模式只能通过 XML 方式配置。。指定参数。包括配置参数 bd.constructorArgumentValues 或外部参数 args。 有参实例调用 autowireConstructor 方法。而无参实例化调用 instantiateBean 方法。无参实例化 instantiateBean 方法比较简单 首先我们了解一下Spring创建Bean的方式 Spring创建对象的主要方式有 通过自定义BeanPostProcessor生成代理对象InstantiationAwareBeanPostProcessor createBean() - resolveBeforeInstantiation() 通过supplier创建对象 createBean() - doCreateBean() - createBeanInstance() - obtainFromSupplier() 通过FactoryMethod创建对象 createBean() - doCreateBean() - createBeanInstance() - instantiateUsingFactoryMethod() 通过反射创建对象 createBean() - doCreateBean() - createBeanInstance() - instantiateBean() 通过FactoryBean创建对象 下面我们一一来看一看 2.3.1 Supplier创建对象 我们先来写一个案例这种用法比较偏门 User package com.shu.supplier;/*** description:* author: shu* createDate: 2023/8/31 14:11* version: 1.0*/ public class User {private String name;public User() {System.out.println(User 无参构造函数);}public User(String name) {this.name name;System.out.println(User 有参构造函数);}public String getName() {return name;}public void setName(String name) {this.name name;System.out.println(User setName);}public void init() {System.out.println(User init);}public void destroy() {System.out.println(User destroy);}Overridepublic String toString() {return User{ name name \ };} } CreateSupplier package com.shu.supplier;/*** description:* author: shu* createDate: 2023/8/31 14:11* version: 1.0*/ public class CreateSupplier {public static User createUser() {User xiaomi new User(xiaomi);System.out.println(CreateSupplier createUser:xiaomi);return xiaomi;} } SupplierBeanFactoryPostProcessor package com.shu.supplier;import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.GenericBeanDefinition;/*** description:* author: shu* createDate: 2023/8/31 14:12* version: 1.0*/ public class SupplierBeanFactoryPostProcessor implements BeanFactoryPostProcessor {Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {BeanDefinition beanDefinition beanFactory.getBeanDefinition(user);GenericBeanDefinition genericBeanDefinition (GenericBeanDefinition) beanDefinition;genericBeanDefinition.setInstanceSupplier(CreateSupplier::createUser);genericBeanDefinition.setBeanClass(User.class);} }配置 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean iduser classcom.shu.supplier.User/beanbean idsupplierBeanFactoryPostProcessor classcom.shu.supplier.SupplierBeanFactoryPostProcessor/bean /beans测试 import com.shu.supplier.User; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource;/*** description:* author: shu* createDate: 2023/7/29 23:05* version: 1.0*/ public class AplTest {/*** 测试FactoryBean*/Testpublic void factoryBeanTestSupplier() {ApplicationContext applicationContext new ClassPathXmlApplicationContext(supplier.xml);User user applicationContext.getBean(User.class);System.out.println(user.getName());}} 下面我们来具体分析看看呗 AbstractAutowireCapableBeanFactory // 如果获取getInstanceSupplier不为空参考genericBeanDefinition.setInstanceSupplier(CreateSupplier::createUser); Supplier? instanceSupplier mbd.getInstanceSupplier();if (instanceSupplier ! null) {return obtainFromSupplier(instanceSupplier, beanName); }下面进入obtainFromSupplier进行看看那么回到这个方法中主体就是调用get()这个方法获取实例 protected BeanWrapper obtainFromSupplier(Supplier instanceSupplier, String beanName) {Object instance;// 获得原当前线程正在创建的 Bean 的名称String outerBean this.currentlyCreatedBean.get();// 设置当前线程正在创建的 Bean 的名称this.currentlyCreatedBean.set(beanName);try {//调用 Supplier 的 get()返回一个实例对象instance instanceSupplier.get();}finally {if (outerBean ! null) {// 设置原当前线程正在创建的 Bean 的名称到当前线程变量中this.currentlyCreatedBean.set(outerBean);}else {this.currentlyCreatedBean.remove();}}// 未创建 Bean 对象则创建 NullBean 空对象if (instance null) {instance new NullBean();}//将实例对象封装成 BeanWrapper 对象BeanWrapper bw new BeanWrapperImpl(instance);//初始化这个 BeanWrapper 对象initBeanWrapper(bw);return bw; } 过程如下 调用 Supplier 接口的 get()返回 instance 实例对象 将 instance 封装成 BeanWrapper 对象 bw 对 bw 进行初始化设置 ConversionService 类型转换器并注册自定义的属性编辑器 然后再进行实例化 AbstractAutowireCapableBeanFactory final Object bean instanceWrapper.getWrappedInstance(); Class? beanType instanceWrapper.getWrappedClass(); if (beanType ! NullBean.class) {mbd.resolvedTargetType beanType; }2.3.2 工厂创建对象 知识回顾 静态工厂实例化 在定义一个用静态工厂方法创建的Bean时使用 class 属性来指定包含 static 工厂方法的类并使用名为 factory-method 的属性来指定工厂方法本身的名称。你应该能够调用这个方法有可选的参数如后文所述并返回一个活的对象随后该对象被视为通过构造函数创建的。 package com.shu.factory;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;/*** description: 静态工厂, 用于书写创建复杂对象的代码* author: shu* createDate: 2023/7/21 20:14* version: 1.0*/ public class StaticConnectionFactory {public static Connection getConnection(){Connection conn null;try {Class.forName(com.mysql.jdbc.Driver);conn DriverManager.getConnection(jdbc:mysql://localhost:3306/auth?useSSLfalse, root, 123456);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}return conn;} }bean iddb classcom.shu.factory.StaticConnectionFactory factory-methodgetConnection//*** 静态工厂实例化bean*/Testpublic void test8(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);Object db context.getBean(db);System.out.println(db db);}实例工厂方法进行实例化 与 通过静态工厂方法进行的实例化 类似用实例工厂方法进行的实例化从容器中调用现有 bean 的非静态方法来创建一个新的 bean。要使用这种机制请将 class 属性留空并在 factory-bean 属性中指定当前或父代或祖代容器中的一个 Bean 的名称该容器包含要被调用来创建对象的实例方法。用 factory-method 属性设置工厂方法本身的名称。 package com.shu.factory;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;public class ConnectionFactory {public Connection getConnection(){Connection conn null;try {Class.forName(com.mysql.jdbc.Driver);conn DriverManager.getConnection(jdbc:mysql://localhost:3306/auth?useSSLfalse, root, 123456);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}return conn;} } bean idconnFactory classcom.shu.factory.ConnectionFactory/beanbean idconn factory-beanconnFactory factory-methodgetConnection/Testpublic void test10() throws Exception {ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);Object conn context.getBean(conn);System.out.println(conn conn);} 让我们回到代码部分 AbstractAutowireCapableBeanFactory //如果配置了 factory-method 工厂方法则调用该方法来创建一个实例对象// 通过 Bean 标注的方法会通过这里进行创建if (mbd.getFactoryMethodName() ! null) {// 这个过程非常复杂你可以理解为// 找到最匹配的 Method 工厂方法获取相关参数依赖注入然后通过调用该方法返回一个实例对象反射机制return instantiateUsingFactoryMethod(beanName, mbd, args);} 通过 factoryMethodName 工厂方法创建一个实例对象例如 XML 配置的 factory-method 属性或者 Bean 标注的方法都会解析成 factoryMethodName 属性 这个过程非常复杂你可以理解为去找到最匹配的 Method 工厂方法获取相关入参依赖注入然后调用该方法返回一个实例对象反射机制 AbstractAutowireCapableBeanFactory protected BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, Nullable Object[] explicitArgs) {return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); }创建 ConstructorResolver 对象然后调用其 instantiateUsingFactoryMethod(…) 方法如下 // ConstructorResolver.java public BeanWrapper instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, Nullable Object[] explicitArgs) {// 构造 BeanWrapperImpl 对象BeanWrapperImpl bw new BeanWrapperImpl();// 初始化 BeanWrapperImpl设置 ConversionService 类型转换器并注册自定义的属性编辑器this.beanFactory.initBeanWrapper(bw);// -------------------------获取工厂方法的相关信息-------------------------//获取工厂方法的相关信息// 工厂方法所在类对应的 Bean静态方法不会有Object factoryBean;// 工厂方法所在类的 Class 对象Class factoryClass;// 是否为 static 修饰的静态方法boolean isStatic;// 获取工厂方法所在类对应的 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);}// 获取工厂方法所在类对应的 Bean不然无法调用工厂方法factoryBean this.beanFactory.getBean(factoryBeanName);// 如果是单例模式已经存在对应的 Bean则抛出重复创建的异常if (mbd.isSingleton() this.beanFactory.containsSingleton(beanName)) {throw new ImplicitlyAppearedSingletonException();}factoryClass factoryBean.getClass();isStatic false;}//静态方法else {// Its a static factory method on the bean class.// 静态方法没有找到对应的 Class 对象无法被调用则抛出异常if (!mbd.hasBeanClass()) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,bean definition declares neither a bean class nor a factory-bean reference);}factoryBean null;factoryClass mbd.getBeanClass();isStatic true;}// -------------------------尝试获取工厂方法对象和入参-------------------------//尝试获取工厂方法对象和参数// 工厂方法对象Method factoryMethodToUse null;ArgumentsHolder argsHolderToUse null;// 方法参数Object[] argsToUse null;//如果方法入参指定了参数则直接使用if (explicitArgs ! null) {argsToUse explicitArgs;}//否则尝试从 RootBeanDefinition 中获取已解析出来的工厂方法和入参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) {// 没有解析过的参数则尝试从 RootBeanDefinition 中获取未被解析过的参数argsToResolve mbd.preparedConstructorArguments;}}}// 如果获取到了未被解析过的入参则进行解析if (argsToResolve ! null) {// 处理参数值类型转换例如给定方法 A(int, int)配置了 A(1、2) 两个参数则会转换为 A(1, 1)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.//获取工厂方法所在的类的实例 Class 对象因为可能是 Cglib 提升过的子类factoryClass ClassUtils.getUserClass(factoryClass);//获取工厂方法所在的类中所有方法对象Method[] rawCandidates getCandidateMethods(factoryClass, mbd);//找到这个类中匹配的工厂方法ListcandidateList new ArrayList();for (Method candidate : rawCandidates) {if (Modifier.isStatic(candidate.getModifiers()) isStatic // 是否和 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]);// 将匹配的方法进行排序public 方法优先入参个数多的优先AutowireUtils.sortFactoryMethods(candidates);// 用于承载解析后的方法参数值ConstructorArgumentValues resolvedValues null;// 是否是构造器注入boolean autowiring (mbd.getResolvedAutowireMode() AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);int minTypeDiffWeight Integer.MAX_VALUE;// 匹配方法的集合SetambiguousFactoryMethods null;// -------------------------确定方法参数的入参数量-------------------------//确定方法参数的入参数量匹配的方法的入参数量要多余它// 方法的参数数量的最小值int minNrOfArgs;//如果当前方法指定了入参则使用其个数作为最小值if (explicitArgs ! null) {minNrOfArgs explicitArgs.length;}//否则从 RootBeanDefinition 解析出方法的参数个数作为最小值else {// We dont have arguments passed in programmatically, so we need to resolve the// arguments specified in the constructor arguments held in the bean definition.// RootBeanDefinition 定义了参数值if (mbd.hasConstructorArgumentValues()) {// 方法的参数ConstructorArgumentValues cargs mbd.getConstructorArgumentValues();resolvedValues new ConstructorArgumentValues();// 解析定义的参数值放入 resolvedValues 中并返回参数个数minNrOfArgs resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);}else {minNrOfArgs 0;}}// 记录 UnsatisfiedDependencyException 异常的集合LinkedListcauses 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;}// 根据参数创建参数持有者 ArgumentsHolder 对象argsHolder new ArgumentsHolder(explicitArgs);}//否则通过**依赖注入**获取入参else {// Resolved constructor arguments: type conversion and/or autowiring necessary.// 为提供参数解析构造参数try {String[] paramNames null;// 获取 ParameterNameDiscoverer 参数名称探测器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) {// 若发生 UnsatisfiedDependencyException 异常添加到 causes 中。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;}}// -------------------------根据权重获取最匹配的方法-------------------------//因为会遍历所有匹配的方法所以需要进行权重的判断拿到最优先的那个// 判断解析构造函数的时候是否以宽松模式还是严格模式默认为 true// 严格模式解析构造函数时必须所有的都需要匹配否则抛出异常// 宽松模式使用具有最接近的模式进行匹配// typeDiffWeight类型差异权重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() paramTypes.length factoryMethodToUse.getParameterCount() !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {// 查找到多个可匹配的方法if (ambiguousFactoryMethods null) {ambiguousFactoryMethods new LinkedHashSet();ambiguousFactoryMethods.add(factoryMethodToUse);}ambiguousFactoryMethods.add(candidate);}}}//没有找到对应的工厂方法则抛出异常if (factoryMethodToUse null) {if (causes ! null) {UnsatisfiedDependencyException ex causes.removeLast();for (Exception cause : causes) {this.beanFactory.onSuppressedException(cause);}throw ex;}ListargTypes new ArrayList(minNrOfArgs);if (explicitArgs ! null) {for (Object arg : explicitArgs) {argTypes.add(arg ! null ? arg.getClass().getSimpleName() : null);}}else if (resolvedValues ! null) {SetvalueHolders 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);}//将解析出来的工厂方法和入参缓存设置到 RootBeanDefinition 中因为整个过程比较复杂避免再次解析if (explicitArgs null argsHolderToUse ! null) {mbd.factoryMethodToIntrospect factoryMethodToUse;argsHolderToUse.storeCache(mbd, factoryMethodToUse);}}Assert.state(argsToUse ! null, Unresolved factory method arguments);//调用工厂方法创建一个实例对象反射机制并设置到 bw 中bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));return bw; }先创建一个 BeanWrapperImpl 对象 bw并初始化设置 ConversionService 类型转换器并注册自定义的属性编辑器 // 构造 BeanWrapperImpl 对象BeanWrapperImpl bw new BeanWrapperImpl();// 初始化 BeanWrapperImpl设置 ConversionService 类型转换器并注册自定义的属性编辑器this.beanFactory.initBeanWrapper(bw);获取工厂方法的相关信息根据 RootBeanDefinition 的 factoryBeanName 属性判断是否为静态方法这个属性表示这个工厂方法所在类对应 Bean 的名称当然静态方法“不属于”这个 Bean所以它的这个属性为空factoryBeanName 属性不为空表示不是静态方法则需要根据 factoryBeanName 找到依赖查找对应的 Bean作为 factoryBean否则就是静态方法获取所在类的 Class 对象即可 // 获取工厂方法所在类对应的 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);}// 获取工厂方法所在类对应的 Bean不然无法调用工厂方法factoryBean this.beanFactory.getBean(factoryBeanName);// 如果是单例模式已经存在对应的 Bean则抛出重复创建的异常if (mbd.isSingleton() this.beanFactory.containsSingleton(beanName)) {throw new ImplicitlyAppearedSingletonException();}factoryClass factoryBean.getClass();isStatic false;}//静态方法else {// Its a static factory method on the bean class.// 静态方法没有找到对应的 Class 对象无法被调用则抛出异常if (!mbd.hasBeanClass()) {throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,bean definition declares neither a bean class nor a factory-bean reference);}factoryBean null;factoryClass mbd.getBeanClass();isStatic true;}:::warning 这一步找到了三个对象factoryBean工厂方法所在类对应的 Bean静态方法不会有、factoryClass工厂方法所在类的 Class 对象、isStatic是否为静态方法。所以想要通过工厂方法获取一个 Bean则需要方法所在类对应的 Bean 先初始化然后才能调用这个方法创建 Bean而静态方法就不用因为它可以根据所在类的 Class 对象就能调用这个方法创建 Bean这就是两者的区别。 ::: 尝试获取工厂方法 Method 对象和入参如果方法入参指定了参数则直接使用否则尝试从 RootBeanDefinition 中获取已解析出来的工厂方法和入参如果获取到了未被解析过的入参则进行解析类型转换例如给定方法 A(int, int)配置了 A(“1”、“2”) 两个参数则会转换为 A(1, 1)这一步尝试获取两个对象factoryMethodToUse对应的工厂方法 Method、argsToUse工厂方法的入参集合 //如果方法入参指定了参数则直接使用if (explicitArgs ! null) {argsToUse explicitArgs;}//否则尝试从 RootBeanDefinition 中获取已解析出来的工厂方法和入参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) {// 没有解析过的参数则尝试从 RootBeanDefinition 中获取未被解析过的参数argsToResolve mbd.preparedConstructorArguments;}}}// 如果获取到了未被解析过的入参则进行解析if (argsToResolve ! null) {// 处理参数值类型转换例如给定方法 A(int, int)配置了 A(1、2) 两个参数则会转换为 A(1, 1)argsToUse resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);}}:::warning 这一步尝试获取两个对象factoryMethodToUse对应的工厂方法 Method、argsToUse工厂方法的入参集合 ::: 如果上一步没有找到工厂方法对象或方法入参集合找到所有匹配的工厂方法首先找到所有匹配的工厂方法获取工厂方法所在的类的实例 Class 对象因为可能是 Cglib 提升过的子类获取工厂方法所在的类中所有方法对象找到这个类中匹配的工厂方法是否和 isStatic 匹配并且和定义的工厂方法的名称是否相等如果只有一个匹配的方法且这个方法没有给指定的入参且本身也没有定义参数且这个方法没有定义入参则直接调用这个方法创建一个实例对象反射机制并返回 // -------------------------找到所有匹配的工厂方法-------------------------//如果上一步没有找到工厂方法对象或方法入参集合则需要进行接下来的解析过程首先找到所有匹配的工厂方法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.//获取工厂方法所在的类的实例 Class 对象因为可能是 Cglib 提升过的子类factoryClass ClassUtils.getUserClass(factoryClass);//获取工厂方法所在的类中所有方法对象Method[] rawCandidates getCandidateMethods(factoryClass, mbd);//找到这个类中匹配的工厂方法ListcandidateList new ArrayList();for (Method candidate : rawCandidates) {if (Modifier.isStatic(candidate.getModifiers()) isStatic // 是否和 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;}}开始找最匹配的工厂方法先排序public 方法优先入参个数多的优先确定方法参数的入参数量匹配的方法的入参数量要多余它如果当前方法指定了入参则使用其个数作为最小值否则从 RootBeanDefinition 解析出方法的参数个数作为最小值没有定义则设置为 0这一步主要是确定入参的个数并排序所有匹配的方法接下来会遍历所有匹配的方法 // -------------------------开始找最匹配的工厂方法-------------------------//开始找最匹配的工厂方法// 将匹配的工厂方法转换成数组Method[] candidates candidateList.toArray(new Method[0]);// 将匹配的方法进行排序public 方法优先入参个数多的优先AutowireUtils.sortFactoryMethods(candidates);// 用于承载解析后的方法参数值ConstructorArgumentValues resolvedValues null;// 是否是构造器注入boolean autowiring (mbd.getResolvedAutowireMode() AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);int minTypeDiffWeight Integer.MAX_VALUE;// 匹配方法的集合SetambiguousFactoryMethods null;// -------------------------确定方法参数的入参数量-------------------------//确定方法参数的入参数量匹配的方法的入参数量要多余它// 方法的参数数量的最小值int minNrOfArgs;//如果当前方法指定了入参则使用其个数作为最小值if (explicitArgs ! null) {minNrOfArgs explicitArgs.length;}//否则从 RootBeanDefinition 解析出方法的参数个数作为最小值else {// We dont have arguments passed in programmatically, so we need to resolve the// arguments specified in the constructor arguments held in the bean definition.// RootBeanDefinition 定义了参数值if (mbd.hasConstructorArgumentValues()) {// 方法的参数ConstructorArgumentValues cargs mbd.getConstructorArgumentValues();resolvedValues new ConstructorArgumentValues();// 解析定义的参数值放入 resolvedValues 中并返回参数个数minNrOfArgs resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);}else {minNrOfArgs 0;}}// 记录 UnsatisfiedDependencyException 异常的集合LinkedListcauses null;:::warning 这一步会找到这个方法的入参依赖注入的方式 ::: 因为会遍历所有匹配的方法所以需要进行权重的判断拿到最优先的那个通常情况下我们只有一个匹配的方法如果存在多个会根据方法的参数类型进行权重 // -------------------------根据权重获取最匹配的方法-------------------------//因为会遍历所有匹配的方法所以需要进行权重的判断拿到最优先的那个// 判断解析构造函数的时候是否以宽松模式还是严格模式默认为 true// 严格模式解析构造函数时必须所有的都需要匹配否则抛出异常// 宽松模式使用具有最接近的模式进行匹配// typeDiffWeight类型差异权重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() paramTypes.length factoryMethodToUse.getParameterCount() !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {// 查找到多个可匹配的方法if (ambiguousFactoryMethods null) {ambiguousFactoryMethods new LinkedHashSet();ambiguousFactoryMethods.add(factoryMethodToUse);}ambiguousFactoryMethods.add(candidate);}}}没有找到对应的工厂方法则抛出异常将解析出来的工厂方法和入参缓存设置到 RootBeanDefinition 中因为整个过程比较复杂避免再次解析 会缓存这几个数据resolvedConstructorOrFactoryMethod已经解析出来的工厂方法、constructorArgumentsResolved方法入参已经解析出来了 true、resolvedConstructorArguments解析出来的入参 //没有找到对应的工厂方法则抛出异常if (factoryMethodToUse null) {if (causes ! null) {UnsatisfiedDependencyException ex causes.removeLast();for (Exception cause : causes) {this.beanFactory.onSuppressedException(cause);}throw ex;}ListargTypes new ArrayList(minNrOfArgs);if (explicitArgs ! null) {for (Object arg : explicitArgs) {argTypes.add(arg ! null ? arg.getClass().getSimpleName() : null);}}else if (resolvedValues ! null) {SetvalueHolders 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);}//将解析出来的工厂方法和入参缓存设置到 RootBeanDefinition 中因为整个过程比较复杂避免再次解析if (explicitArgs null argsHolderToUse ! null) {mbd.factoryMethodToIntrospect factoryMethodToUse;argsHolderToUse.storeCache(mbd, factoryMethodToUse);}}调用工厂方法创建一个实例对象反射机制并设置到 bw 中 Assert.state(argsToUse ! null, Unresolved factory method arguments);//调用工厂方法创建一个实例对象反射机制并设置到 bw 中bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));return bw;上面整个过程非常复杂这里进行简单概括 找到对应的工厂方法如果是非静态方法则需要先依赖查找到所在类对应的 Bean因为需要根据这个 Bean 去调用对应的工厂方法而静态方法不用可以根据其 Class 对象调用对应的工厂方法如果工厂方法有入参则需要注入相关对象依赖注入调用这个方法反射机制返回一个实例对象 2.3.3 构造器创建实例 当你用构造函数的方法创建一个Bean时所有普通的类都可以被Spring使用并与之兼容。也就是说被开发的类不需要实现任何特定的接口也不需要以特定的方式进行编码。只需指定Bean类就足够了。然而根据你对该特定Bean使用的IoC类型你可能需要一个默认空构造函数。 无参构造 package com.shu.pojo;/*** description:* author: shu* createDate: 2023/7/20 23:34* version: 1.0*/ public class User {private String name;public User() {System.out.println(User的无参构造);}public User(String name) {this.name name;System.out.println(User的有参构造);}public String getName() {return name;}public void setName(String name) {this.name name;System.out.println(User的setName方法);}public void show() {System.out.println(name name);} } !-- 无参构造 --bean iduser classcom.shu.pojo.User/ /*** 构造函数实例化bean*/Testpublic void test6(){ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);User user (User) context.getBean(user);user.show();} 有参构造 介绍有参构造之前我们需要了解依赖注入的概念 依赖注入DI是一个过程对象仅通过构造参数、工厂方法的参数或在对象实例被构造或从工厂方法返回后在其上设置的属性来定义它们的依赖即与它们一起工作的其它对象。然后容器在创建 bean 时注入这些依赖。这个过程从根本上说是Bean本身通过使用类的直接构造或服务定位模式来控制其依赖的实例化或位置的逆过程因此被称为控制反转。采用DI原则代码会更干净当对象被提供其依赖时解耦会更有效。对象不会查找其依赖也不知道依赖的位置或类别。因此你的类变得更容易测试特别是当依赖是在接口或抽象基类上时这允许在单元测试中使用stub或mock实现。DI有两个主要的变体基于构造器的依赖注入 和 基于setter的依赖注入。 构造器依赖注入 基于构造函数的 DI 是通过容器调用带有许多参数的构造函数来完成的每个参数代表一个依赖。 !-- 有参构造 --bean iduser2 classcom.shu.pojo.Userconstructor-arg namename valueshu//bean package com.shu.pojo;/*** description:* author: shu* createDate: 2023/7/20 23:34* version: 1.0*/ public class User {private String name;public User() {System.out.println(User的无参构造);}public User(String name) {this.name name;System.out.println(User的有参构造);}public String getName() {return name;}public void setName(String name) {this.name name;System.out.println(User的setName方法);}public void show() {System.out.println(name name);} } Setter的依赖注入 基于 Setter 的 DI 是通过容器在调用无参数的构造函数或无参数的 static 工厂方法来实例化你的 bean 之后调用 Setter 方法来实现的。简单来说就是调用了你的set发放完成赋值这也决定我们需要编写Set方法的实现当然这也是我们Spring中常用的实例化 bean iduser classcom.shu.pojo.Userproperty namename valueshu//bean 下面我们来具体看看代码部分 AbstractAutowireCapableBeanFactory // 构造器实例化 // 4. 快速实例化对象所谓的快速实例化实际上是说使用缓存boolean resolved false;boolean autowireNecessary false;// 4.1 args: 外部化参数只能当无外部参数时才使用缓存。不推荐使用外部化参数if (args null) {synchronized (mbd.constructorArgumentLock) {// 4.2 是否使用缓存其中autowireNecessary表示是否使用有参构造器// 无参时肯定不会解析为false。有参时会解析为trueif (mbd.resolvedConstructorOrFactoryMethod ! null) {resolved true;autowireNecessary mbd.constructorArgumentsResolved;}}}// 4.3 使用缓存其中autowireNecessary表示是否使用有参构造器if (resolved) {if (autowireNecessary) {// 4.4 有参构造器实例化return autowireConstructor(beanName, mbd, null, null);} else {// 4.5 无参构造器实例化return instantiateBean(beanName, mbd);}}// 5. 到此只能老老实实的解析当然解析后会将解析后的构造器或参数缓存起来// 5.1 是否指定了构造器ibp#determineCandidateConstructorsConstructor?[] ctors determineConstructorsFromBeanPostProcessors(beanClass, beanName);// 5.2 构造器实例化if (ctors ! null || mbd.getResolvedAutowireMode() AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}// 5.3 不用管默认都是 null。ctors mbd.getPreferredConstructors();if (ctors ! null) {return autowireConstructor(beanName, mbd, ctors, null);}// 5.4 无参构造器实例化return instantiateBean(beanName, mbd); }我们可以看到上面代码的两个关键方法有参实例化与无参实例化 autowireConstructor实例化 这个过程和上一个方法一样非常复杂不过差不太多你可以理解为去找到当前 Bean 的构造方法获取相关入参构造器注入然后调用该构造方法返回一个实例对象反射机制 AbstractAutowireCapableBeanFactory protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, Nullable Constructor[] ctors, Nullable Object[] explicitArgs) {return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs); }创建 ConstructorResolver 对象然后调用其 autowireConstructor(…) 方法 ConstructorResolver // ConstructorResolver.java public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,Nullable Constructor[] chosenCtors, Nullable Object[] explicitArgs) {// 构造 BeanWrapperImpl 对象BeanWrapperImpl bw new BeanWrapperImpl();// 初始化 BeanWrapperImpl设置 ConversionService 类型转换器并注册自定义的属性编辑器this.beanFactory.initBeanWrapper(bw);// -------------------------尝试获取构造方法和入参-------------------------//尝试获取构造方法和入参// 构造方法Constructor constructorToUse null;ArgumentsHolder argsHolderToUse null;// 构造方法的入参集合Object[] argsToUse null;//如果当前方法入参指定了参数则直接使用if (explicitArgs ! null) {argsToUse explicitArgs;}//否则尝试从 RootBeanDefinition 中获取已解析出来的构造方法和入参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) {// 没有解析过的参数则尝试从 RootBeanDefinition合并后中获取未被解析过的参数argsToResolve mbd.preparedConstructorArguments;}}}// 如果获取到了未被解析过的入参if (argsToResolve ! null) {// 处理参数值类型转换例如给定方法 A(int, int)配配置了 A(1、2) 两个参数则会转换为 A(1, 1)argsToUse resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);}}// -------------------------开始获取构造方法和入参-------------------------//如果上一步没有找到构造方法或入参集合找到所有匹配的工厂方法首先找到所有匹配的构造方法if (constructorToUse null || argsToUse null) {// Take specified constructors, if any.//获取所有的构造方法如果当前方法指定了构造方法的集合则使用这个集合Constructor[] candidates chosenCtors;if (candidates null) {Class beanClass mbd.getBeanClass();try {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);}}//如果构造方法只有一个且当前方法的入参没有指定参数且本身也没有定义参数且这个构造方法没有定义入参// 则直接调用这个构造方法创建一个实例对象反射机制并返回if (candidates.length 1 explicitArgs null !mbd.hasConstructorArgumentValues()) {Constructor uniqueCandidate candidates[0];if (uniqueCandidate.getParameterCount() 0) {synchronized (mbd.constructorArgumentLock) {mbd.resolvedConstructorOrFactoryMethod uniqueCandidate;mbd.constructorArgumentsResolved true;mbd.resolvedConstructorArguments EMPTY_ARGS;}bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));return bw;}}// Need to resolve the constructor.// 是否是构造器注入boolean autowiring (chosenCtors ! null ||mbd.getResolvedAutowireMode() AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);// 用于承载解析后的方法参数值ConstructorArgumentValues resolvedValues null;// -------------------------确定构造方法的入参数量-------------------------//确定构造参数的入参数量匹配的方法的入参数量要多余它// 方法的参数数量的最小值int minNrOfArgs;if (explicitArgs ! null) {minNrOfArgs explicitArgs.length;}// 从 RootBeanDefinition 解析出方法的参数个数作为最小值else {ConstructorArgumentValues cargs mbd.getConstructorArgumentValues();resolvedValues new ConstructorArgumentValues();minNrOfArgs resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);}//将所有的构造方法进行排序public 方法优先入参个数多的优先AutowireUtils.sortConstructors(candidates);int minTypeDiffWeight Integer.MAX_VALUE;SetConstructor ambiguousConstructors null;LinkedListcauses null;// 遍历所有构造函数for (Constructor candidate : candidates) {// 获取该构造方法的参数类型Class[] paramTypes candidate.getParameterTypes();// 如果前面已经找到匹配的构造方法和入参则直接结束循环if (constructorToUse ! null argsToUse ! 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 {// 获取构造方法的参数名称ConstructorProperties 注解String[] paramNames ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);if (paramNames null) {// 没有获取到则通过 ParameterNameDiscoverer 参数探测器获取参数名称ParameterNameDiscoverer pnd this.beanFactory.getParameterNameDiscoverer();if (pnd ! null) {paramNames pnd.getParameterNames(candidate);}}// 解析出方法的入参参数值会被依赖注入argsHolder createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,getUserDeclaredConstructor(candidate), autowiring, candidates.length 1);}catch (UnsatisfiedDependencyException ex) {if (logger.isTraceEnabled()) {logger.trace(Ignoring constructor [ candidate ] of bean beanName : ex);}// Swallow and try next constructor.if (causes null) {causes new LinkedList();}causes.add(ex);continue;}}//如果当前方法的入参指定了参数如果个数相等则直接使用else {// Explicit arguments given - arguments length must match exactly.if (paramTypes.length ! explicitArgs.length) {continue;}argsHolder new ArgumentsHolder(explicitArgs);}// -------------------------根据权重获取最匹配的方法-------------------------//因为会遍历所有匹配的方法所以需要进行权重的判断拿到最优先的那个// 判断解析构造函数的时候是否以宽松模式还是严格模式默认为 true// 严格模式解析构造函数时必须所有的都需要匹配否则抛出异常// 宽松模式使用具有最接近的模式进行匹配// typeDiffWeight类型差异权重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();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);}//将解析出来的工厂方法和入参缓存设置到 RootBeanDefinition 中因为整个过程比较复杂避免再次解析if (explicitArgs null argsHolderToUse ! null) {argsHolderToUse.storeCache(mbd, constructorToUse);}}Assert.state(argsToUse ! null, Unresolved constructor arguments);//调用这个构造方法返回一个实例对象反射机制并设置到 bw 中bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));return bw; }详细的步骤参考上面的工厂创建的解析我们这里总结一下’ 上**面整个过程非常复杂这里进行简单概括** 找到最匹配的构造方法如果构造方法有入参则需要注入相关对象构造器注入其实也是依赖注入获取到的参数调用这个构造方法反射机制返回一个实例对象 instantiateBean 方法 兜底方法如果构造方法找不到或者已经解析出来的构造方法则直接使用默认的构造方法或者已经解析出来的构造方法返回一个实例对象 AbstractAutowireCapableBeanFactory // AbstractAutowireCapableBeanFactory.java protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {try {Object beanInstance;final BeanFactory parent this;// 安全模式if (System.getSecurityManager() ! null) {beanInstance AccessController.doPrivileged((PrivilegedAction) () -// 获得 InstantiationStrategy 对象并使用它创建 Bean 对象getInstantiationStrategy().instantiate(mbd, beanName, parent),getAccessControlContext());}else {// 获得 InstantiationStrategy 对象并使用它创建 Bean 对象beanInstance 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);} }可以看到会通过 CglibSubclassingInstantiationStrategy#instantiate(…) 方法创建一个实例对象该方法如下 SimpleInstantiationStrategy Override public Object instantiate(RootBeanDefinition bd, Nullable String beanName, BeanFactory owner) {// Dont override the class with CGLIB if no overrides.//没有 MethodOverride 对象也就是没有需要覆盖或替换的方法则直接使用反射机制进行实例化即可if (!bd.hasMethodOverrides()) {Constructor constructorToUse;synchronized (bd.constructorArgumentLock) {//尝试从 RootBeanDefinition 获得已经解析出来的构造方法 resolvedConstructorOrFactoryMethodconstructorToUse (Constructor) bd.resolvedConstructorOrFactoryMethod;//没有解析出来的构造方法则获取默认的构造方法if (constructorToUse null) {final Class clazz bd.getBeanClass();// 如果是接口抛出 BeanInstantiationException 异常if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, Specified class is an interface);}try {// 从 clazz 中获得构造方法if (System.getSecurityManager() ! null) { // 安全模式constructorToUse AccessController.doPrivileged((PrivilegedExceptionActionConstructor) clazz::getDeclaredConstructor);}else {constructorToUse clazz.getDeclaredConstructor();}// 标记 resolvedConstructorOrFactoryMethod 属性bd.resolvedConstructorOrFactoryMethod constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, No default constructor found, ex);}}}//通过这个构造方法实例化一个对象反射机制return BeanUtils.instantiateClass(constructorToUse);}//否则通过 CGLIB 生成一个子类对象else {// Must generate CGLIB subclass.return instantiateWithMethodInjection(bd, beanName, owner);} }过程大致如下 没有 MethodOverride 对象也就是没有需要覆盖或替换的方法则直接使用反射机制进行实例化即可尝试从 RootBeanDefinition 获得已经解析出来的构造方法 resolvedConstructorOrFactoryMethod没有解析出来的构造方法则获取默认的构造方法通过这个构造方法实例化一个对象反射机制否则通过 CGLIB 生成一个子类对象 到这我们就介绍完了Bean的创建基础知识参考Spring 的基本介绍_长安不及十里的博客-CSDN博客 下面回到doCreatBean方法中 2.4 Bean的前置处理 AbstractAutowireCapableBeanFactory // Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,Post-processing of merged bean definition failed, ex);}mbd.postProcessed true;}} 找到所有实现了MergedBeanDefinitionPostProcessor的实例 然后访问其postProcessMergedBeanDefinition()方法。这里主要是为了后面填充Bean属性做一些前置准备。 由于篇幅原因我们下篇文章详细解决下面的流程
http://www.w-s-a.com/news/423662/

相关文章:

  • icp备案和网站不符查询公司的网站备案
  • 万江营销型网站建设泰安网站建设制作电话号码
  • 做网站是用ps还是ai服饰东莞网站建设
  • 只做一页的网站多少钱网站开发就业趋势
  • 陈村网站建设有哪些网站可以做店面设计
  • 查询网站注册信息wordpress 照片墙
  • 成都网站设计服务商室内设计设计师网站推荐
  • 企业建站系统cms百度网址ip
  • wordpress 代码编辑插件下载搜索引擎优化seo课程总结
  • 韩都衣舍网站建设的改进邯郸公众号小程序制作
  • 上海设计网站建设在线视频制作
  • 东营高端网站建设新建网站如何让百度收录
  • wordpress怎么生成网站地图微网站平台怎样做网站
  • 同安区建设局网站招投标公众号简介有趣的文案
  • 江苏州 网站制作网上宣传方法有哪些
  • 做网站时怎样申请域名郑州制作网站公司
  • 深圳 网站开发公司电话网站关键词快排名
  • 网站建设的工作总结seo同行网站
  • 网站需要兼容哪些浏览器sql数据库做的网站怎么发布
  • 营销型网站的建站步骤是什么意思广州门户网站建设公司
  • 汕尾好网站建设推广计算机软件包含网站开发
  • 建设工程施工许可证在哪个网站办wordpress更换主题白屏
  • 微交易网站建设wordpress摘要调用
  • 做网站维护需要懂什么网站后台后缀名
  • 网站建设的认可桂平市住房和城乡建设局网站
  • 网站设计师岗位职责域名关键词查询
  • 百度怎样建设网站盐城公司网站建设
  • 站长工具国产2023网站制作 商务
  • 网络新闻专题做的最好的网站杭州网站设计建设公司
  • 电商网站界面设计流程ps培训班一般学费多少钱