1.Springä¹FactoryBean
2.学习编程|Spring源码深度解析 读书笔记 第4章:bean的加载
3.Spring Cloud OpenFeign源码FeignClientFactoryBean原理
4.spring源码解析bean初始化与依赖注入四
5.JSF源码分析(一)
6.Springä¸BeanFactoryä¸FactoryBeançä½ç¨ä¸åºå«
Springä¹FactoryBean
ä¸è¬æ åµä¸ï¼Spring éè¿åå°æºå¶å©ç¨bean ç classå±æ§æå®å®ç°ç±»æ¥å®ä¾åbeanãå¨æäºæ åµä¸ï¼å®ä¾å bean çè¿ç¨ä¸å«å¤æï¼å¦ææç §ä¼ ç»çæ¹å¼ï¼åéè¦å¨ <bean> ä¸æä¾å¤§éçé 置信æ¯ï¼é ç½®ççµæ´»åº¦åéï¼è¿æ¶åéç¨ç¼ç çæ¹å¼å¯è½ä¼å¾å°ä¸ä¸ªç®åçæ¹æ³ãSpringæä¾äºä¸ä¸ªorg.springframework.bean.FactoryBeançå·¥åæ¥å£ï¼ç¨æ·å¯ä»¥éè¿å®ç°è¯¥æ¥å£å®å¶å®ä¾åçbeanãFactoryBeanæ¥å£å¯¹äºSpringæ¡æ¶æ¥è¯´å ç¨éè¦çå°ä½ï¼Springæ¬èº«å°±æä¾äºç¹å«å¤çFactoryBeançå®ç°ãå®ä»¬éèäºå®ä¾åå¤æbeançç»èï¼ç»ä¸å±åºç¨å¸¦æ¥äºä¾¿å©ãFactoryBeançæºç å¦ä¸ï¼
å¨è¯¥æ¥å£ä¸å®ä¹äºä¸ä¸ªæ¹æ³ï¼
å½é ç½®æä»¶ä¸ <bean> çclasså±æ§é ç½®å®ç°çæ¯FactoryBeanæ¶ï¼éè¿getBean()æ¹æ³è¿åçä¸æ¯ FactoryBean æ¬èº«ï¼èæ¯ FactoryBean ç getObject() æ¹æ³è¿åç对象ã
ä¾å¦ä½¿ç¨ä¼ ç»çæ¹å¼é ç½®ä¸é¢çStudentç <bean> çæ¶ï¼Studentçæ¯ä¸ä¸ªå±æ§é½ä¼å¯¹åºä¸ä¸ª <property> å ç´ çæ ç¾ã
å¦æ使ç¨FactoryBeançæ¹å¼å®ç°å°±æ´çµæ´»ä¸äºï¼éè¿ä¸é¢çéå·åé符çæ¹å¼ä¸æ¬¡æ§å°ä¸ºStudentçææå±æ§æå®é ç½®å¼ï¼
æäºè¿ä¸ä¸ªStudentFactoryBeanåï¼å°±å¯ä»¥å¨é ç½®æ件ä¸ä½¿ç¨ä¸é¢çè¿ç§æ¹æ³é ç½®StudentBeanäºã
å½è°ç¨ getBean("student") æ¶ï¼Springéè¿åå°æºå¶åç° StudentFactoryBean#getObject() æ¹æ³çè¿åãå¦æå¸æè·å StudentFactoryBean çå®ä¾ï¼åéè¦ä½¿ç¨ getBean(beanName) æ¹æ³æ¶å¨beanNameåæ¾ç¤ºçå ä¸ "&" åç¼ï¼ä¾å¦ getBean("&student") ã
学习编程|Spring源码深度解析 读书笔记 第4章:bean的加载
在Spring框架中,bean的加载过程是一个精细且有序的过程。首先,当需要加载bean时,Spring会尝试通过转换beanName来识别目标对象,可能涉及到别名或FactoryBean的路亚之家源码识别。
加载过程分为几步:从缓存查找单例,Spring容器内单例只创建一次,若缓存中无数据,会尝试从singletonFactories寻找。接着是bean的实例化,从缓存获取原始状态后,可能需要进一步处理以符合预期状态。
原型模式的依赖检查是单例模式特有的,用来避免循环依赖问题。然后,如果缓存中无数据,会检查parentBeanFactory,递归加载配置。BeanDefinition会被转换为RootBeanDefinition,合并父类属性,确保依赖的正确初始化。
Spring根据不同的scope策略创建bean,如singleton、prototype等。类型转换是后续步骤,可能将返回的影像设计源码bean转换为所需的类型。FactoryBean的使用提供了灵活的实例化逻辑,用户自定义创建bean的过程。
当bean为FactoryBean时,getBean()方法代理了FactoryBean的getObject(),允许通过不同的方式配置bean。缓存中获取单例时,会执行循环依赖检测和性能优化。最后,通过ObjectFactory实例singletonFactory定义bean的完整加载逻辑,包括回调方法用于处理单例创建前后的状态。
Spring Cloud OpenFeign源码FeignClientFactoryBean原理
Spring Cloud OpenFeign的FeignClientFactoryBean在实例化过程中,通过FactoryBean接口实现,GetObject方法的关键步骤包括获取FeignContext、配置Feign.Builder、创建HardCodedTarget和调用loadBalance方法。这些步骤涉及自动配置、FeignClientSpecification的使用、Logger和Builder组件的定制以及动态代理的生成。最后,getObject方法返回的是一个接口的代理类,用于执行远程调用。
详细分析:
FeignClientFactoryBean在Spring容器中,通过getObject方法转化为实际的FeignClient实例。首先,它从FeignContext获取相关配置,这个配置在引入OpenFeign依赖时自动注入。firefox源码解析接下来,通过getTarget方法,FeignClientFactoryBean配置了Builder组件,如Logger(非Slf4j)、RequestInterceptor、Encoder和Decoder等,同时考虑了用户自定义组件的配置。之后,创建了HardCodedTarget,基于FeignClient接口、注解值和完整URL构建,然后通过loadBalance方法,整合了LoadBalancerFeignClient和HystrixTargeter,进行负载均衡和目标URL定位。
在newInstance方法中,解析了接口方法的注解,生成了MethodHandler,并用FeignInvocationHandler封装,这个InvocationHandler在代理类实例化时被调用,实现了远程调用。最终,通过Proxy.newProxyInstance动态生成了代理类,完成FeignClientFactoryBean的实例化过程。
总的来说,FeignClientFactoryBean实例化是通过一系列配置和代理生成,实现了Spring Cloud OpenFeign的java中介源码远程调用功能。如果你对源码的深入理解感兴趣,下期文章将继续解析调用源码细节。
spring源码解析bean初始化与依赖注入四
深入解析Spring源码的bean初始化与依赖注入部分,我们将继续从上一篇文章的
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean方法入手。
随后,方法调用
org.springframework.beans.factory.support.AbstractBeanFactory#registerDisposableBeanIfNecessary进行注册
紧接着,调用
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean获取bean实例。
在这一过程中,我们到达了
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingleton用于销毁单例bean。
然后,再次深入
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean方法进行bean的创建。
紧接着,调用
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation对bean进行前置解析。
之后,再次返回
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean进行bean实例化。
然后,调用
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean再次获取bean实例。
紧接着,进入
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons进行单例bean的预实例化。
最终,完成bean的初始化后触发回调。
返回
org.springframework.context.support.AbstractApplicationContext#refresh执行上下文刷新,完成bean初始化与依赖注入。
至此,本次关于Spring源码中bean初始化与依赖注入的解析告一段落,以上内容仅供学习参考。民警网站源码
JSF源码分析(一)
在深入分析 JSF 框架的源码时,我们首先关注的是核心的功能模块,以帮助我们理解其工作原理。通常,我们从常见的项目 XML 配置文件入手,这些文件包含了 JSF 框架的基本设置。让我们以地址服务的 jsf-provider.xml 文件为例,进行详细的解析。
在 JSF 的配置文件中,虽然没有直接显示注册中心的内容,但作为自研的高性能 RPC 调用框架,高可用的注册中心是其核心功能之一。因此,我们接下来将探索如何在没有提供注册中心地址的情况下,这些标签是如何完成服务的注册和订阅的。
### 配置解析
首先,我们发现配置文件中自定义的 xsd 文件,通过 NamespaceUri 链接到 jsf.jd.com/schema/jsf/j...。随后,基于 SPI(Service Provider Interface)机制,我们在 META-INF 中找到了定义好的 Spring.handlers 文件和 Spring.schemas 文件,这两个文件分别用于配置解析器和 xsd 文件的具体路径。
进一步地,我们查询了继承自 NamespaceHandlerSupport 或实现 NamespaceHandler 接口的类。在 JSF 框架中,JSFNamespaceHandler 通过继承 NamespaceHandlerSupport 实现了对自定义命名空间的解析功能。NamespaceHandler 的主要作用是解析我们自定义的 JSF 命名空间,通过 BeanDefinitionParser 对特定标签进行处理,完成对 XML 中配置信息的具体处理。
### 服务暴露
最终,通过 JSFBeanDefinitionParser 实现了 org.springframework.beans.factory.xml.BeanDefinitionParser,完成 XML 配置的解析。解析的结果会注册到 BeanDefinitionRegistry 对象中,进而触发 Bean 的初始化过程。最终,ProviderBean 实例监听上下文事件,在容器初始化完毕后,调用 export() 方法进行服务的暴露。
### 服务注册与暴露
服务暴露的实现逻辑集中在 ProviderConfig#doExport 方法中。首先,方法会对配置进行基本校验和拦截。随后,获取所有 RegistryConfig,如果获取不到注册中心地址,将使用默认的注册中心地址:“i.jsf.jd.com”。接着,根据 Provider 配置中的 server 相关信息启动 server,并使用默认序列化方式(如 msgpack)进行服务编码。然后,通过 ServerFactory 初始化并启动 Server,调用 ServerTransportFactory 生成对应的传输层,实现与注册中心的通信。最后,服务注册通过 JSFRegistry 类完成,该类连接注册中心,如果没有可用的中心,则使用本地文件并开启守护线程,使用两个线程池进行心跳检测、重试机制和连接状态监控。至此,服务从配置装配到服务暴露的过程完成。
### 消费者配置与初始化
对于消费者端(jsf-consumer.xml),注册中心地址(如“i.jsf.jd.com”)被配置在其中,而 Provider 的配置则在 jsf-provider.xml 中。配置解析过程与 Provider 类似,最终解析为 ConsumerConfig 和 RegistryConfig。通过 ConsumerBean 类实现 FactoryBean 接口,以便通过 getObject() 方法获取代理对象,完成客户端的初始化。在这个过程中,消费者会根据配置订阅相关的 Provider 服务。核心代码在 ConsumerConfig#refer 方法中,该方法通过调用子类的 subscribe() 方法开始订阅过程,连接 Provider 服务。
### 框架流程概述
综上所述,JSF 框架通过 Provider、Consumer 和注册中心(Registry)之间的协同工作,实现了高效的服务注册、订阅和通信。具体流程包括:
1. **Provider 端**:启动服务向注册中心注册,并根据配置初始化相关组件。
2. **Consumer 端**:首次获取实体信息时,通过 FactoryBean 接口获取代理对象,完成初始化并订阅 Provider 服务。
3. **注册中心**:提供异步通知机制,监控服务状态变化。
4. **服务调用**:直接调用服务方法。
5. **监控与治理**:框架内置监控机制,支持服务治理和降级容灾策略。
了解这一过程对于深入理解 JSF 框架的内部机制至关重要,也为后续的模块分析和系统优化提供了基础。
Springä¸BeanFactoryä¸FactoryBeançä½ç¨ä¸åºå«
Spring Frameworkï¼ä»å¹´å¤å¤©ä½ å¯è½å·²ç»å¬è§å¾å¤ç议论ãå¨æ¬æä¸,æå°è¯å¾è§£éSpringè½å®æä»ä¹ï¼åææä¹ä¼è®¤ä¸ºå®è½å¸®å©ä½ å¼åJ2EEåºç¨ç¨åºã å¦ä¸frameworkï¼ ä½ å¯è½æ£å¨æ³âä¸è¿æ¯å¦å¤ä¸ä¸ªçframeworkâãå½å·²ç»æ许å¤å¼æ¾æºä»£ç (åä¸æ) J2EE frameworkæ¶ï¼ä¸ºä»ä¹ä½ åºè¯¥è´¹å¿è¯»è¿ç¯æç« ,æä¸è½½Spring Frameworkï¼ æç¸ä¿¡Springæ¯ç¬ç¹ç,å 为è¥å¹²ä¸ªåå : . å®å®ä½çé¢åæ¯è®¸å¤å ¶ä»æµè¡çframework没æçãSpringå ³æ³¨æä¾ä¸ç§æ¹æ³ç®¡çä½ çä¸å¡å¯¹è±¡ã . Springæ¯å ¨é¢çå模ååçãSpringæåå±çä½ç³»ç»æ,è¿æå³çä½ è½éæ©ä½¿ç¨å®å¤ç«çä»»ä½é¨å,å®çæ¶æä»ç¶æ¯å å¨ç¨³å®çãå æ¤ä»ä½ çå¦ä¹ ä¸ï¼ä½ å¯å¾å°æ大çä»·å¼ãä¾å¦,ä½ å¯è½éæ©ä» ä» ä½¿ç¨Springæ¥ç®ååJDBCç使ç¨,æç¨æ¥ç®¡çææçä¸å¡å¯¹è±¡ã . å®ç设计ä»åºé¨å¸®å©ä½ ç¼åæäºæµè¯ç代ç ãSpringæ¯ç¨äºæµè¯é©±å¨å·¥ç¨ççæ³çframeworkã Springå¯¹ä½ çå·¥ç¨æ¥è¯´ï¼å®ä¸éè¦ä¸ä¸ªä»¥ä¸çframeworkãSpringæ¯æ½å¨å°ä¸ç«å¼è§£å³æ¹æ¡,å®ä½äºä¸å ¸ååºç¨ç¸å ³ç大é¨ååºç¡ç»æãå®ä¹æ¶åå°å ¶ä»framework没æèèå°çå 容ã 尽管å®ä» ä» æ¯ä¸ä¸ªä»å¹´2ææå¼å§çå¼æºå·¥ç¨ï¼ä½Springæè¾é¿çåå²æ ¹åºãè¿ä¸ªå¼æºå·¥ç¨æ¯èµ·æºèªæå¨å¹´åæåºççãExpert One-on-One J2EE设计ä¸å¼åã书ä¸çåºç¡ä»£ç ãè¿æ¬ä¹¦å±ç¤ºäºSpringèåçåºç¡æ¶æãç¶è,è¿ä¸ªåºç¡æ¶æçæ¦å¿µè¦è¿½æº¯å°å¹´çæ©äºæ¶å,并ä¸åæ äºæ为ä¸ç³»åæåçåä¸å·¥ç¨å¼ååºç¡ç»æçç»éªã ä»å¹´1æï¼Springå·²ç»è½æ·äºSourceForgeä¸ãç°å¨æ个å¼å人å,å ¶ä¸6æ¯é«åº¦æå ¥ç积æååã Springçæ¶ææ§çå¥½å¤ å¨æ们è¿å ¥ç»è以åï¼è®©æ们çä¸ä¸Springå¯ä»¥ç»ä¸ä¸ªå·¥ç¨å¸¦æ¥çä¸äºå¥½å¤: . Springè½ææå°ç»ç»ä½ çä¸é´å±å¯¹è±¡,æ è®ºä½ æ¯å¦éæ©ä½¿ç¨äºEJBãå¦æä½ ä» ä» ä½¿ç¨äºStrutsæå ¶ä»çå å«äºJ2EEç¹æAPIsçframeworkï¼ä½ ä¼åç°Springå ³æ³¨äºéçä¸çé®é¢ï¼ã . Springè½æ¶é¤å¨è®¸å¤å·¥ç¨ä¸å¯¹Singletonçè¿å¤ä½¿ç¨ãæ ¹æ®æçç»éªï¼è¿æ¯ä¸ä¸ªä¸»è¦çé®é¢ï¼å®åå°äºç³»ç»çå¯æµè¯æ§åé¢å对象ç¹æ§ã . Springè½æ¶é¤ä½¿ç¨åç§åæ ·æ ¼å¼çå±æ§å®å¶æ件çéè¦,å¨æ´ä¸ªåºç¨åå·¥ç¨ä¸ï¼å¯éè¿ä¸ç§ä¸è´çæ¹æ³æ¥è¿è¡é ç½®ãæ¾ç»æå°è¿·æï¼ä¸ä¸ªç¹å®ç±»è¦æ¥æ¾è¿·å¹»è¬çå±æ§å ³é®åæç³»ç»å±æ§,为æ¤ä¸å¾ä¸è¯»Javadocä¹è³æºç¼ç åï¼æäºSpringï¼ä½ å¯å¾ç®åå°çå°ç±»çJavaBeanå±æ§ãåç½®æ§å¶ç使ç¨(å¨ä¸é¢è®¨è®º)帮å©å®æè¿ç§ç®åã . Springè½éè¿æ¥å£èä¸æ¯ç±»ä¿è¿å¥½çç¼ç¨ä¹ æ¯ï¼åå°ç¼ç¨ä»£ä»·å°å ä¹ä¸ºé¶ã . Spring被设计为让使ç¨å®å建çåºç¨å°½å¯è½å°çä¾èµäºä»çAPIsãå¨Springåºç¨ä¸ç大å¤æ°ä¸å¡å¯¹è±¡æ²¡æä¾èµäºSpringã . 使ç¨Springæ建çåºç¨ç¨åºæäºåå æµè¯ã . Springè½ä½¿EJBç使ç¨æ为ä¸ä¸ªå®ç°éæ©,èä¸æ¯åºç¨æ¶æçå¿ ç¶éæ©ãä½ è½éæ©ç¨POJOsælocal EJBsæ¥å®ç°ä¸å¡æ¥å£ï¼å´ä¸ä¼å½±åè°ç¨ä»£ç ã . Spring帮å©ä½ 解å³è®¸å¤é®é¢èæ é使ç¨EJBãSpringè½æä¾ä¸ç§EJBçæ¿æ¢ç©ï¼å®ä»¬éäºè®¸å¤webåºç¨ãä¾å¦,Springè½ä½¿ç¨AOPæä¾å£°ææ§äºå¡èä¸éè¿ä½¿ç¨EJB容å¨ï¼å¦æä½ ä» ä» éè¦ä¸å个çæ°æ®åºæ交éï¼çè³ä¸éè¦JTAå®ç°ã . Spring为æ°æ®ååæä¾äºä¸è´çæ¡æ¶,ä¸è®ºæ¯ä½¿ç¨JDBCæO/R mapping产åï¼å¦Hibernateï¼ã Springç¡®å®ä½¿ä½ è½éè¿æç®åå¯è¡ç解å³åæ³è§£å³ä½ çé®é¢ãè¿äºç¹æ§æ¯æå¾å¤§ä»·å¼çã Springè½åä»ä¹ï¼ Springæä¾è®¸å¤åè½,å¨æ¤æå°å¿«éå°ä¾æ¬¡å±ç¤ºå ¶å个主è¦æ¹é¢ã ä»»å¡æè¿°ï¼ é¦å ,让æ们æç¡®Springèå´ã尽管Springè¦çäºè®¸å¤æ¹é¢ï¼ä½æ们已ç»ææ¸ æ¥çæ¦å¿µï¼å®ä»ä¹åºè¯¥æ¶ååä»ä¹ä¸åºè¯¥æ¶åã Springç主è¦ç®çæ¯ä½¿J2EEæç¨åä¿è¿å¥½ç¼ç¨ä¹ æ¯ã Springä¸éæ°å¼åå·²æçä¸è¥¿ãå æ¤ï¼å¨Springä¸ä½ å°åç°æ²¡ææ¥å¿è®°å½çå ,没æè¿æ¥æ± ,没æåå¸äºå¡è°åº¦ãè¿äºåæå¼æºé¡¹ç®æä¾(ä¾å¦Commons Logging ç¨æ¥åææçæ¥å¿è¾åºï¼æCommons DBCPç¨æ¥ä½æ°æ®è¿æ¥æ± ),æç±ä½ çåºç¨ç¨åºæå¡å¨æä¾ãå 为åæ ·ççåå ï¼æ们没ææä¾O/R mappingå±ï¼å¯¹æ¤ï¼å·²ææ好ç解å³åæ³å¦HibernateåJDOã Springçç®æ æ¯ä½¿å·²åå¨çææ¯æ´å æç¨ãä¾å¦,尽管æ们没æåºå±äºå¡åè°å¤çï¼ä½æ们æä¾äºä¸ä¸ªæ½è±¡å±è¦çäºJTAæä»»ä½å ¶ä»çäºå¡çç¥ã Spring没æç´æ¥åå ¶ä»çå¼æºé¡¹ç®ç«äºï¼é¤éæ们æå°æ们è½æä¾æ°çä¸äºä¸è¥¿ãä¾å¦ï¼è±¡è®¸å¤å¼å人åï¼æ们ä»æ¥æ²¡æ为Strutsé«å ´è¿ï¼å¹¶ä¸æå°å¨MVC web frameworkä¸è¿ææ¹è¿çä½å°ãå¨æäºé¢åï¼ä¾å¦è½»é级çIoC容å¨åAOPæ¡æ¶ï¼Springæç´æ¥çç«äºï¼ä½æ¯å¨è¿äºé¢åè¿æ²¡æå·²ç»è¾ä¸ºæµè¡ç解å³æ¹æ¡ã(Springå¨è¿äºåºåæ¯å¼è·¯å éã) Springä¹å¾çäºå å¨çä¸è´æ§ã ææçå¼åè é½å¨å±åæ ·ççèµæ,åºç¡æ³æ³ä¾ç¶æ¯Expert One-on-One J2EE设计ä¸å¼åçé£äºã 并ä¸æ们已ç»è½å¤ä½¿ç¨ä¸äºä¸»è¦çæ¦å¿µ,ä¾å¦åç½®æ§å¶ï¼æ¥å¤çå¤ä¸ªé¢åã Springå¨åºç¨æå¡å¨ä¹é´æ¯å¯ç§»æ¤çã å½ç¶ä¿è¯å¯ç§»æ¤æ§æ»æ¯ä¸æ¬¡ææï¼ä½æ¯æ们é¿å ä»»ä½ç¹å®å¹³å°æéæ åå,并ä¸æ¯æå¨WebLogicï¼Tomcatï¼Resinï¼JBossï¼WebSphereåå ¶ä»çåºç¨æå¡å¨ä¸çç¨æ·ã åç½®æ§å¶å®¹å¨ Springçè®¾è®¡æ ¸å¿æ¯ org.springframework.beans å , 为ä¸JavaBeansä¸èµ·å·¥ä½è设计ã è¿ä¸ªå ä¸è¬ä¸ç´æ¥è¢«ç¨æ·ä½¿ç¨, ä½ä½ä¸ºåºç¡ä¸ºæ´å¤çå ¶ä»åè½æå¡. ä¸ä¸ä¸ªè¾é«å±é¢çæ½è±¡æ¯"Bean Factory"ã Spring bean factory æ¯ä¸ä¸ªæ®éçFactoryï¼å®ä½¿å¯¹è±¡è½å¤æå称è·åï¼å¹¶ä¸è½ç®¡ç对象ä¹é´çå ³ç³»ã Bean factories æ¯æ两ç§å¯¹è±¡æ¨¡å¼: . Singletonï¼å¨æ¤æ¨¡å¼ä¸ï¼æä¸ä¸ªå ·æç¹å®å称çå ±äº«å¯¹è±¡å®ä¾ï¼å®å¨æ¥æ¾æ¶è¢«è·åãè¿æ¯é»è®¤çï¼èä¸æ¯æ为ç»å¸¸ä½¿ç¨çãå®å¯¹äºæ ç¶æ对象æ¯ä¸ç§çæ³ç模å¼ã .Prototypeï¼å¨æ¤æ¨¡å¼ä¸ï¼æ¯æ¬¡è·åå°å建ä¸ä¸ªç¬ç«ç对象ãä¾å¦ï¼è¿å¯ä»¥è¢«ç¨äºå 许ç¨æ·æ¥æä»ä»¬èªå·±ç对象ã ç±äº org.springframwork.beans.factory.BeanFactoryæ¯ä¸ä¸ªç®åçæ¥å£ï¼å®è½è¢«ä¸ºäºåºå±åå¨æ¹æ³èå®ç°ãä½ è½å¤æ¹ä¾¿å°å®ç°ä½ èªå·±çBeanFactoryï¼å°½ç®¡å¾å°ç¨æ·éè¦ãæ为常ç¨çå®ä¹æ¯ï¼ .XmlBeanFactoryï¼ å¯è§£æç®åç´è§çå®ä¹ç±»åå½å对象å±æ§çXMLç»æã æ们æä¾äºä¸ä¸ªDTDæ¥ä½¿ç¼åæ´å®¹æã .ListableBeanFactoryImplï¼å¯æä¾è§£æåæ¾å¨å±æ§æ件ä¸çbeanå®ä¹ï¼åå¯éè¿ç¼ç¨å建BeanFactoriesã æ¯ä¸ªbeanå®ä¹å¯è½æ¯ä¸ä¸ªPOJO(éè¿ç±»ååJavaBeanåå§å±æ§å®ä¹)ï¼ææ¯ä¸ä¸ªFactoryBeanãFactoryBeanæ¥å£æ·»å äºä¸ä¸ªé´æ¥å±ãé常ï¼è¿ç¨äºä½¿ç¨AOPæå ¶ä»æ¹æ³æ¥å建代ç对象ï¼ä¾å¦ï¼æ·»å äºå£°ææ§äºå¡ç®¡çç代çã(è¿å¨æ¦å¿µä¸åEJB侦å¬ç¸ä¼¼ï¼ä½å¨å®è·µä¸å®ç°æ´ç®åã) BeanFactoriesè½å¨ä¸ä¸ªå±æ¬¡ç»æä¸å¯éæ©æ§çåä¸ï¼æ ¹æ®æ¥èªç¥å ç继æ¿å®ä¹ãè¿ä½¿å¨æ´ä¸ªåºç¨ä¸å ¬å ±é ç½®çå ±äº«æ为å¯è½ï¼è½ç¶ä¸ªå«èµæºï¼å¦controller servletsï¼ä¹æ¥æä»ä»¬èªå·±çç¬ç«ç对象éåã è¿ç§ä½¿ç¨JavaBeansçå¨æºå¨ç第åç« ä¸ææè¿°ï¼å¨TheServerSideç½ç«ä¸çæå è´¹çPDF(). éè¿BeanFactoryæ¦å¿µï¼Springæ为ä¸ä¸ªåç½®æ§å¶ç容å¨ã(æé常ä¸å欢containerè¿ä¸ªæ¯è¯ï¼å 为å®ä½¿äººèæ³å°éé级容å¨ï¼å¦EJB容å¨ãSpringçBeanFactoryæ¯ä¸ä¸ªå¯éè¿ä¸è¡ä»£ç å建ç容å¨ï¼å¹¶ä¸ä¸éè¦ç¹æ®çé¨ç½²æ¥éª¤ã) ä½äºåç½®æ§å¶èåçæ¦å¿µæ¯å¨Hollywoodååä¸ç»å¸¸è¡¨è¿°ï¼"Donât call me, Iâll call you." IoCå°æ§å¶èè´£æ¬è¿äºæ¡æ¶ä¸ï¼å¹¶è±ç¦»åºç¨ä»£ç ãæ¶åå°é ç½®çå°æ¹ï¼æææ¯è¯´å¨ä¼ ç»ç容å¨ä½ç³»ç»æä¸ï¼å¦EJBï¼ä¸ä¸ªç»ä»¶å¯ä»¥è°ç¨å®¹å¨å¹¶é®âæéè¦å®ç»æåå·¥ä½ç对象Xå¨åªé?âï¼ä½¿ç¨IoC容å¨ååªéæåºç»ä»¶éè¦X对象ï¼å¨è¿è¡æ¶å®¹å¨ä¼æä¾ç»å®ã容å¨åºäºæ¹æ³åä½åºè¿ç§è¯´æï¼æå¯è½æ ¹æ®é ç½®æ°æ®å¦XMLã åç½®æ§å¶çå 个éè¦å¥½å¤ãå¦ï¼ . å 为ç»ä»¶ä¸éè¦å¨è¿è¡æ¶é´å¯»æ¾åä½è ï¼æ以ä»ä»¬å¯ä»¥æ´ç®åçç¼ååç»´æ¤ãå¨SpringçIoCçæ¬éï¼ç»ä»¶éè¿æ´é²JavaBeançsetteræ¹æ³è¡¨è¾¾ä»ä»¬ä¾èµçå ¶ä»ç»ä»¶ãè¿ç¸å½äºEJBéè¿JNDIæ¥æ¥æ¾ï¼EJBæ¥æ¾éè¦å¼å人åç¼å代ç ã . åæ ·åå ï¼åºç¨ä»£ç æ´å®¹ææµè¯ãJavaBeanå±æ§æ¯ç®åçï¼Javaæ ¸å¿çï¼å¹¶ä¸å®¹ææµè¯ï¼ä» ç¼åä¸ä¸ªå å«èªèº«çJunitæµè¯æ¹æ³ç¨æ¥å建对象å设置ç¸å ³å±æ§å³å¯ã . ä¸ä¸ªå¥½çIoCå®ç°éèäºå¼ºç±»åãå¦æä½ ä½¿ç¨ä¸ä¸ªæ®éçfactoryæ¥å¯»æ¾åä½è ï¼ä½ å¿ é¡»éè¿ç±»å转æ¢å°è¿åç»æ转å为æ³è¦çç±»åãè¿ä¸æ¯ä¸ä¸ªä¸»è¦é®é¢ï¼ä½æ¯ä¸é è§ã使ç¨IoCï¼ä½ å¨ä½ ç代ç ä¸è¡¨è¾¾å¼ºç±»åä¾èµï¼æ¡æ¶å°è´è´£ç±»å转æ¢ãè¿æå³çå¨æ¡æ¶é ç½®åºç¨æ¶ï¼ç±»åä¸å¹é å°å¯¼è´é误ï¼å¨ä½ ç代ç ä¸ï¼ä½ æ éæ å¿ç±»å转æ¢å¼å¸¸ã . 大é¨åä¸å¡å¯¹è±¡ä¸ä¾èµäºIoC容å¨çAPIsãè¿ä½¿å¾å¾å®¹æ使ç¨éçä¸æ¥ç代ç ï¼ä¸å¾å®¹æç使ç¨å¯¹è±¡æ 论å¨å®¹å¨å æä¸å¨å®¹å¨å ãä¾å¦ï¼Springç¨æ·ç»å¸¸é ç½®Jakarta Commons DBCPæ°æ®æºä¸ºä¸ä¸ªSpring beanï¼ä¸éè¦äºä»»ä½å®å¶ä»£ç å»åè¿ä»¶äºãæ们说ä¸ä¸ªIoC容å¨ä¸æ¯ä¾µå ¥æ§çï¼ä½¿ç¨å®å¹¶ä¸ä¼ä½¿ä½ ç代ç ä¾èµäºå®çAPIsãä»»ä½JavaBenaå¨Spring bean factoryä¸é½è½æ为ä¸ä¸ªç»ä»¶ã æååºè¯¥å¼ºè°çæ¯ï¼IoC ä¸åäºä¼ ç»ç容å¨çä½ç³»ç»æ( å¦EJB), åºç¨ä»£ç æå°ç¨åº¦çä¾é äºå®¹å¨ãè¿æå³çä½ çä¸å¡å¯¹è±¡å¯ä»¥æ½å¨ç被è¿è¡å¨ä¸åçIoC æ¡æ¶ä¸-æè å¨ä»»ä½æ¡æ¶ä¹å¤-ä¸éè¦ä»»ä½ä»£ç æ¹ã 以æçç»éªåä½ä¸ºSpringç¨æ·ï¼è¿å强è°IoCç»åºç¨ä»£ç 带æ¥ç好å¤æ¯ä¸å®¹æçã IoCä¸æ¯ä¸ä¸ªæ°æ¦å¿µï¼ä½æ¯å®å¨J2EEå¢ä½éé¢ååå°è¾¾é»éæ¶é´ã æä¸äºå¯ä¾éæ©çIoC 容å¨: notably, Apache Avalon, PicoContainer å HiveMind. Avalon ä¸ä¼æ为ç¹å«æµè¡çï¼å°½ç®¡å®å¾å¼ºå¤§èä¸æå¾é¿çåå²ãAvalonæ¯ç¸å½çéé级åå¤æçï¼å¹¶ä¸çèµ·æ¥æ¯æ°çIoC解å³æ¹æ¡æ´å ·ä¾µå ¥æ§ã PicoContaineræ¯ä¸ä¸ªè½»é级èä¸æ´å¼ºè°éè¿æé å¨è¡¨è¾¾ä¾èµæ§èä¸æ¯JavaBean å±æ§ã
6. Spring源码篇之FactoryBean
FactoryBean是Spring提供的一个功能强大的小型工厂,用于灵活创建所需Bean。在框架与Spring整合时,尤其是Mybatis-plus中,通过注解可以自动生成Spring Bean,而FactoryBean的功能正是实现批量动态生成Bean。下面详细介绍FactoryBean的源码解析。
首先,我们来看看如何判断一个对象是否为FactoryBean。在Spring的实例化过程中,如果类实现了FactoryBean接口,则会被识别为FactoryBean。而获取FactoryBean时,通常在Bean名称前加上"&"符号。
接下来,我们深入分析FactoryBean的接口。
FactoryBean接口定义了如何创建Bean,包含两个主要方法:getObject和isInstance。getObject用于返回创建的Bean实例,isInstance用于判断一个对象是否由FactoryBean创建。
SmartFactoryBean是FactoryBean的子接口,它提供了额外的特性,允许决定是否提前实例化对象。
在实际使用中,FactoryBean的实例化过程较为关键。如果不希望立即实例化某个非懒加载单例Bean,则需要确保它未被识别为FactoryBean。例如,UserBean的实例化代码在正常情况下不会打印任何输出,表明并未实例化。而通过将UserBean实现为SmartFactoryBean,并使isEagerInit返回true,就能在控制台中观察到UserBean的实例化过程。
获取FactoryBean创建的Bean有多种方式。通过在Bean名称前加"&",可以获取到由getObject方法生成的Bean。此外,若需要获取FactoryBean本身,则可以使用多个"&"符号,Spring会循环遍历,直至获取到实际的Bean。
在Spring实例化完成后,通常会调用getObjectForBeanInstance方法来获取真正的Bean实例。这一过程包括了共享实例(sharedInstance)的引用和Bean名称的处理。最终,通过调用getObject方法,我们能够获取到由FactoryBean生成的实际Bean。
以Mybatis-plus中的MapperFactoryBean为例,说明了如何在实际项目中应用FactoryBean。MapperFactoryBean是Mybatis-plus提供的一个FactoryBean,用于自动注册Mapper接口为Spring Bean。
总结而言,FactoryBean在Spring中扮演着灵活创建和管理Bean的重要角色,尤其在需要动态生成或自定义Bean创建逻辑的场景中。通过理解其源码和使用方法,开发者可以更高效地整合各类框架与Spring,实现更为灵活和高效的系统构建。