- 浏览: 378216 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
真的全站唯一:
描述的能不能准确一点,我也以为bigDecimal性能比dou ...
【性能】Java BigDecimal和double性能比较 -
zhanggang807:
学习到了。。以后会考虑往这方面设计
【java规范】Java spi机制浅谈 -
Xiong506:
xiyuan1025 写道你这是在linux下吗,我在linu ...
[监控]Btrace监控简单笔记 -
Xiong506:
xiyuan1025 写道你这是在linux下吗,我在linu ...
[监控]Btrace监控简单笔记 -
Bll:
找不到实现类
【java规范】Java spi机制浅谈
接上文:
本文将解析spring bean定义标签和自定义标签的解析实现原理。
这里说的标签仅限于以xml作为bean定义描述符的spring容器,继承AbstractXmlApplicationContext的一些子 容器,如XmlApplicationContext、ClassPathXmlApplicationContext、 FileSystemXmlApplicationContext等。同时也仅限于描述schema作为标签定义的情况。
Spring xml ioc 容器常用标签和自定义标签
以 Xml 资源定义的容器配置是我们最常见的一种方式。
Spring 容器需要解析 xml 的标签,并把 xml 里 bean 的定义转化为内部的结构 BeanDifinition 。
Spring 的标签有很多种,其支持的常见的标签有:
标签 | 说明 | 例子 |
<bean> | 最常用的,定义一个普通 bean。 |
<bean id="myBean" class="com.test.MyBean" lazy-init="true"/> |
<tx> | 如<tx: advice> 等,提供事务配置通用支持。 |
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*"/> <tx:method name="remove*"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> |
<aop> | <aop:config>,<aop: aspectj-autoproxy> 等提供代理 bean 通用配置支持。 |
<aop:config proxy-target-class="true"> <aop:advisor pointcut="..." advice-ref="txAdvice"/> <aop:advisor pointcut="..." advice-ref="fooAdvice"/> </aop:config> |
<util> | 提供在容器内配置一些JDK自带的工具类、集合类和常量的支持。 |
<util:list id="list" list-class="java.util.ArrayList"> <value>listValue1</value> <value>listValue2</value> </util:list> <util:map id="map"> <entry key="key1" value="mapValue1"></entry> <entry key="key12" value="mapValue2"></entry> </util:map> |
<p> | 属性的简单访问 |
<bean id="loginAction" class="com.test.LoginAction" p:name="test"></bean> |
<lang> | <lang:groovy><lang:jruby>等,提供对动态脚本的支持。 |
<lang:groovy id="test" refresh-check-delay="5000" script-source="classpath:com/test/groovy/test.groovy"> </lang:groovy> |
<jee > | <jee:jndi-lookup/>等,对一些javaEE规范的bean配置的简化,如jndi等。 |
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource" cache="true" resource-ref="true" lookup-on-startup="false" expected-type="com.myapp.DefaultFoo" proxy-interface="com.myapp.Foo"/> |
基本上每一种标签都是用来定义一类 bean 的(P标签除外)。以上都是 spring 自带的一些标签,当然 spring 也支持自定义标签。其实 <tx><aop> 这些也可以认为是自定义标签,不过是由 spring 扩展的而已。
其实所有的bean定义都可以用bean标签来实现定义的。而衍生这种自定义标签来定义 bean 有几个好处:
1. 见名知意。
2. 对于同一类的通用 bean 。封装不必要的配置,只给外部暴露一个简单易用的标签和一些需要配置的属性。很多时候对于一个框架通用的 bean ,我们不需要把 bean 的所有配置都暴露出来,甚至像类名、默认值等我们都想直接封装,这个时候就可以使用自定义标签了,如: <services:property-placeholder /> 可能这个标签就默认代表配置了一个支持 property placeholder 的通用 bean ,我们都不需要去知道配这样一个 bean 的类路径是什么。
可以说自定义标签是 spring 的 xml 容器的一个扩展点,本身 spring 自己的很多标签也是基于这个设计上面来构造出来的。
Spring 对于自定义(声明式)bean标签解析如何设计
Bean 的定义方式有千千万万种,无论是何种标签,无论是何种资源定义,无论是何种容器,最终的 bean 定义内部表示都将转换为内部的唯一结构: BeanDefinition 。外部的各种定义说白了就是为了方便配置。
Spring 提供对其支持的标签解析的天然支持。所以只要按照 spring 的规范编写 xml 配置文件。所有的配置,在启动时都会正常的被解析成 BeanDefinition 。但是如果我们要实现一个自定义标签,则需要提供对自定义标签的全套支持。
我们知道要去完成一个自定义标签,需要完成的事情有:
1. 编写自定义标签 schema 定义文件,放在某个 classpath 下。
2. 在 classpath 的在 META-INF 下面增加 spring.schemas 配置文件,指定 schema 虚拟路径和实际 xsd 的映射。我们在 xml 里的都是虚拟路径,如:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd "> <bean id="otherBean" class="com.test.OtherBean" scope="prototype"/> <bean id="myBean" class="com.test.MyBean" lazy-init="true"/> <bean id="singletonBean" class="com.test.SingletonBean"/> </beans>
头部的
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
就是一个虚拟路径,其对应的真实路径在spring jar包里的META-INF/spring.schemas里面有映射到classpath定义:
http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
3. 增加一个 NamespaceHandler 和 BeanDefinitionParser ,用于解析自定义的标签,将自定义标签的 bean 解析成一个 BeanDefinition 返回。
4. 在 classpath 的在 META-INF 下面增加 spring.handlers 配置文件,指定标签命名空间和 handlers 的映射。
为什么要做以上几个事情?我们来看看设计:
Spring 对标签解析的设计的过程如下:
解释:
Step 1: 将 xml 文件解析成 Dom 树。将 xml 文件解析成 dom 树的时候,需要 xml 标签定义 schema 来验证文件的语法结构。 Spring 约定将所有的 shema 的虚拟路径和真是文件路径映射定义在 classpath 的在 META-INF/spring.schemas 下面。在容器启动时 Spring 会扫描所有的 META-INF/spring.schemas 并将映射维护到一个 map 里。
如 spring jar 包里会有自带的标签的 schemas 映射,可以看一下部分配置:
http\://www.springframework.org/schema/aop/spring-aop-2.0.xsd = org/springframework/aop/config/spring-aop-2.0.xsd http\://www.springframework.org/schema/aop/spring-aop-2.5.xsd = org/springframework/aop/config/spring-aop-2.5.xsd http\://www.springframework.org/schema/aop/spring-aop.xsd = org/springframework/aop/config/spring-aop-2.5.xsd http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd = org/springframework/beans/factory/xml/spring-beans-2.0.xsd http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd = org/springframework/beans/factory/xml/spring-beans-2.5.xsd http\://www.springframework.org/schema/beans/spring-beans.xsd = org/springframework/beans/factory/xml/spring-beans-2.5.xsd http\://www.springframework.org/schema/context/spring-context-2.5.xsd = org/springframework/context/config/spring-context-2.5.xsd http\://www.springframework.org/schema/context/spring-context.xsd = org/springframework/context/config/spring-context-2.5.xsd http\://www.springframework.org/schema/jee/spring-jee-2.0.xsd = org/springframework/ejb/config/spring-jee-2.0.xsd http\://www.springframework.org/schema/jee/spring-jee-2.5.xsd = org/springframework/ejb/config/spring-jee-2.5.xsd ......
等号左边是虚拟路径,右边是真是路径(classpath下的)。
虚拟路径用在我们的bean定义配置文件里,如:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd> <bean> </beans>
beans里面的
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
就是个虚拟路径。
Step 2: 将 dom 树解析成 BeanDifinition 。将定义 bean 的标签和 xml 定义解析成 BeanDefinition 的过程。如果是默认的 bean 标签, spring 会直接进行解析。而如果不是默认的 bean 标签,包括自定义和 spring 扩展的 <aop> 、 <p> 、 <util> 等标签,则需要提供专门的 xmlparser 来处理。 paorser由自己定义和编写,并通过handler注册到容器。Spring 约定了 META-INF/spring.handlers 文件,在这里面定义了标签命名空间和 handler 的映射。容器起来的时候会加载 handler , handler 会向容器注册该命名空间下的标签和解析器。在解析的自定义标签的时候, spring 会根据标签的命名空间和标签名找到一个解析器。由该解析器来完成对该标签内容的解析,并返回一个 BeanDefinition 。
以下是 spring jar 包自带的一些自定义标签扩展的 spring.handlers 文件,可以看到定义了 aop\p 等其扩展标签的 handlers 。
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler http\://www.springframework.org/schema/jms=org.springframework.jms.config.JmsNamespaceHandler http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
META-INF/spring.handlers
看看UtilNamespaceHandler的代码实现
public void init() { registerBeanDefinitionParser("constant", new ConstantBeanDefinitionParser()); registerBeanDefinitionParser("property-path", new PropertyPathBeanDefinitionParser()); registerBeanDefinitionParser("list", new ListBeanDefinitionParser()); registerBeanDefinitionParser("set", new SetBeanDefinitionParser()); registerBeanDefinitionParser("map", new MapBeanDefinitionParser()); registerBeanDefinitionParser("properties", new PropertiesBeanDefinitionParser()); }
实现了标签和对应parser的映射注册。
ListBeanDefinitionParser的实现如下:
private static class ListBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected Class getBeanClass(Element element) { return ListFactoryBean.class; } protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String listClass = element.getAttribute("list-class"); List parsedList = parserContext.getDelegate().parseListElement(element, builder.getRawBeanDefinition()); builder.addPropertyValue("sourceList", parsedList); if (StringUtils.hasText(listClass)) { builder.addPropertyValue("targetListClass", listClass); } String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } }
这里父类代码不贴了,主要完成的是beanDifinition的生成。
源码实现
Spring 对于自定义(声明式)bean标签源码实现大概的源码结构如下:
XmlBeanDefinitionReader 是核心类,它接收 spring 容器传给它的资源 resource 文件,由它负责完成整个转换。它调用 DefaultDocumentLoader 来完成将 Resource 到 Dom 树的转换。调用 DefaultBeanDefinitionDocumentReader 完成将 Dom 树到 BeanDefinition 的转换。
具体的代码流程细节完全可以基于这个结构去阅读,下面就贴几个核心源码段:
源码段 1 : 加载 spring.shemas,在PluggableSchemaResolver.java里实现:
public class PluggableSchemaResolver implements EntityResolver { /***定义schema location的映射文件路径***/ public static final String DEFAULT_SCHEMA_MAPPINGS_LOCATION = "META-INF/spring.schemas"; private static final Log logger = LogFactory.getLog(PluggableSchemaResolver.class); private final ClassLoader classLoader; private final String schemaMappingsLocation; /** Stores the mapping of schema URL -> local schema path */ private Properties schemaMappings; public PluggableSchemaResolver(ClassLoader classLoader) { this.classLoader = classLoader; this.schemaMappingsLocation = DEFAULT_SCHEMA_MAPPINGS_LOCATION; } public PluggableSchemaResolver(ClassLoader classLoader, String schemaMappingsLocation) { Assert.hasText(schemaMappingsLocation, "'schemaMappingsLocation' must not be empty"); this.classLoader = classLoader; this.schemaMappingsLocation = schemaMappingsLocation; } /**==========中间省略部分代码=========**/ /***此处完成schema的加载***/ protected String getSchemaMapping(String systemId) { if (this.schemaMappings == null) { if (logger.isDebugEnabled()) { logger.debug("Loading schema mappings from [" + this.schemaMappingsLocation + "]"); } try { this.schemaMappings = PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation, this.classLoader); if (logger.isDebugEnabled()) { logger.debug("Loaded schema mappings: " + this.schemaMappings); } } catch (IOException ex) { throw new FatalBeanException( "Unable to load schema mappings from location [" + this.schemaMappingsLocation + "]", ex); } } return this.schemaMappings.getProperty(systemId); } }
源码段 2 : 加载 spring.handlers,在 DefaultNamespaceHandlerResolver里实现:
public class DefaultNamespaceHandlerResolver implements NamespaceHandlerResolver { /** * The location to look for the mapping files. Can be present in multiple JAR files. */ public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers"; /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); /** ClassLoader to use for NamespaceHandler classes */ private final ClassLoader classLoader; /** Resource location to search for */ private final String handlerMappingsLocation; /** Stores the mappings from namespace URI to NamespaceHandler class name / instance */ private Map handlerMappings; public DefaultNamespaceHandlerResolver() { this(null, DEFAULT_HANDLER_MAPPINGS_LOCATION); } public DefaultNamespaceHandlerResolver(ClassLoader classLoader) { this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION); } public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) { Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null"); this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); this.handlerMappingsLocation = handlerMappingsLocation; } /**==========中间省略部分代码=========**/ /************************ * Load the specified NamespaceHandler mappings lazily. * 此处加载延迟加载spring.handlers,只有第一次自定义标签被解析到,才会被加载。 ****************************/ private Map getHandlerMappings() { if (this.handlerMappings == null) { try { Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader); if (logger.isDebugEnabled()) { logger.debug("Loaded mappings [" + mappings + "]"); } this.handlerMappings = new HashMap(mappings); } catch (IOException ex) { IllegalStateException ise = new IllegalStateException( "Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]"); ise.initCause(ex); throw ise; } } return this.handlerMappings; } }
源码段3 : xml 到 dom 树的解析。
在 XmlBeanDefinitionReader .java 的 doLoadBeanDefinitions 方法里,调用 DefaultDocumentLoader 完成。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = getValidationModeForResource(resource); Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (SAXParseException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); } catch (SAXException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex); } catch (ParserConfigurationException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex); } catch (IOException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex); } catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); } }
其中的
getEntityResolver()
会完成spring.schemas的装载,里面会间接调用源码段1。穿进去的entityResolver作为标签解析使用。
源码段4 : dom 树到 Beandifinition:
在 XmlBeanDefinitionReader .java 的 doLoadBeanDefinitions 方法里,调用 BeanDefinitionDocumentReader 完成。
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // Support old XmlBeanDefinitionParser SPI for backwards-compatibility. if (this.parserClass != null) { XmlBeanDefinitionParser parser = (XmlBeanDefinitionParser) BeanUtils.instantiateClass(this.parserClass); return parser.registerBeanDefinitions(this, doc, resource); } // Read document based on new BeanDefinitionDocumentReader SPI. BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
具体细节这里不在累述。
总结
spring标签的扩展性做得还是不错的。在我们公司很多框架的一些通用配置都基于spring的声明式标签来实现。中间的一些约定和设计思想值得学习。 本文很多代码细节没办法累述,有兴趣可以去看看。文章中若有不对的地方请大家指出,一起探讨。
后续的spring源码学习可能会是代理的具体实现,欢迎一起探讨!
评论
对于这一点,其实BeanDefinitionParser 不是必须的,直接在Handler里面解析dom,
然后注册到BeanFactory,这样能更清晰地展示Handler的处理逻辑
发表评论
-
【总结】近期的几点技术心得总结
2012-09-09 09:29 2081近期做了好长时间的 ... -
【java规范】Java spi机制浅谈
2012-04-24 23:04 45839最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现 ... -
Xml ResourceBundle简单实现
2012-04-17 21:45 4456ResourceBundle主要是用于和本地语言环境相关的一些 ... -
【java基础】如何设计java应用程序的平滑停止
2012-03-05 23:44 10999java应用程序退出的触发机制有: 1.自动结束:应用没有存 ... -
【JDBC,数据库】Oracle date和timestamp类型混用时需要注意的索引失效问题
2011-12-14 15:27 89551.关于 Oracle date和timestamp类型 D ... -
【性能】JDBC PreparedStatement和连接池PreparedStatement Cache学习记录
2011-12-08 17:20 16872之前看JDBC规范的时候对PreparedStatement只 ... -
【工具】svn几个容易忘记属性设置命令备忘
2011-11-08 13:32 296搭建项目,添加工程经常把svn的几个属性设置命令忘记了,老是要 ... -
【Spring】IOC核心源码学习(二):容器初始化过程
2011-09-21 21:03 23647接上文 啃啃老菜: Spring IOC核心源码学习(一 ... -
【设计】一个有意思的服务方法入参设计
2011-09-01 22:40 2022今天晚上和项目组的几 ... -
【Spring】IOC容器并发条件下,可能发生死锁
2011-08-28 17:07 69251.背景 上周在生产环境应用启 ... -
啃啃老菜:Spring IOC核心源码学习(一)
2011-08-14 13:57 7523啃啃老菜: Spring IOC核心源码 ...
相关推荐
在Spring框架中,Bean的初始化是其生命周期中的关键步骤,特别是在单例模式下,Spring容器会确保在应用程序启动时...理解这些源码细节有助于我们更好地掌握Spring的工作原理,从而更有效地进行Spring应用的开发和优化。
标题《Spring IoC源码深度剖析开源架构源码2021.pdf》和描述《Spring IoC源码深度剖析开源架构源码2021.pdf》表明该文档主要面向于分析Spring框架中控制反转(IoC)容器的核心源码,解析和理解其内部的工作机制及...
在本文中,我们将深入探讨Spring IOC的概念、工作原理,并通过源码分析来理解其实现方式。 首先,控制反转(IOC)是指将对象的创建和管理权限交由一个外部容器(即Spring容器)来负责,而不是由代码本身直接控制。...
理解Spring IoC的源码实现对于Java开发者至关重要,它能帮助我们更深入地了解Spring框架的工作原理,从而更高效地利用Spring进行编程。通过阅读和分析源码,我们可以学习到如何配置和管理Bean,以及如何自定义Bean的...
标签 "源码" 暗示我们将深入 Spring 框架的内部,了解 IOC 容器的工作原理。Spring 源码是用 Java 编写的,遵循模块化的架构。当我们谈论源码时,可能会关注以下几个关键点: 1. `BeanDefinition`:每个 Bean 在...
【标题】"Java进阶之SpringIoC源码深度剖析共19页.pd" 提供的是一项关于Java开发中的高级主题,特别是针对Spring框架的依赖注入(Inversion of Control,IoC)部分的深入研究。Spring IoC是Spring框架的核心特性之一...
**模拟Spring的IOC** ...这不仅有助于理解Spring的工作原理,也为我们自定义轻量级框架提供了可能。在实际开发中,了解并掌握Spring的IOC机制能够帮助我们更好地设计和组织代码,提升代码的灵活性和可维护性。
本文将基于Spring 2.0版本的源码,深入分析Spring IOC容器的内部实现机制,帮助读者更好地理解和使用这一强大的工具。 #### 二、核心概念与术语 在深入探讨Spring IOC容器之前,我们首先需要了解几个核心的概念: ...
总之,通过分析这个"Spring5IOC项目源码",我们可以深入学习Spring的IoC机制,了解如何利用注解进行配置,掌握基于Java的配置方式,理解AOP的实现原理,以及Spring如何处理高并发和反应式编程。这些知识对于提升Java...
综上所述,这个自定义Spring核心功能项目源码涵盖了Spring框架的核心特性,包括IOC、DI的实现,SpringMVC的使用,以及AOP和事务管理。通过深入学习和实践这个项目,开发者不仅可以深化对Spring的理解,还能提升在...
《Spring IOC源码解析(一)——整体介绍》 在深入理解Spring框架的过程中,源码分析是不可或缺的一环。本文将对Spring的IOC(Inversion of Control,控制反转)容器的源码进行初步探讨,旨在帮助读者从整体上把握...
这个简单的实现虽然不能与Spring的复杂功能相提并论,但它足够说明了IOC和反射在Java中实现解耦和依赖注入的基本原理。通过这种方式,我们可以更好地理解和模仿Spring框架的工作方式,为后续深入学习和使用Spring...
在这个名为"Spring-IOC丐版"的项目中,我们将深入探讨Spring框架的核心组件——IOC容器的基础实现。 IOC,即控制反转,是一种设计模式,它的主要思想是将对象的创建和管理权交给一个外部容器,而不是由对象自身负责...
在Spring框架中,"工厂Bean"是一个非常关键的概念,它扩展了传统的Bean定义,使得我们可以在Spring IoC容器中创建自定义的实例化逻辑。工厂Bean允许开发者在对象实例化时进行更复杂的控制,比如引入特定的初始化过程...
Spring允许开发者定义bean的初始化方法和销毁方法,以实现自定义的生命周期行为。此外,还涉及了bean的生命周期状态,如单例bean的实例化时机以及原型bean的每次请求都会创建新实例等。 2. **Spring_0700_IOC_...
通过学习和分析Java_minispring,开发者不仅可以深入理解Spring的核心原理,还能培养解决问题和调试源码的能力。对于那些想要进一步探索Spring框架的人来说,这是一个非常有价值的资源。同时,它也可以作为教学材料...
Spring框架的核心组件依赖于多个第三方库,包括但不限于AOP(面向切面编程)库、IoC(控制反转)库、Bean工厂库等。这些库通常被打包成jar文件,以便在开发环境中引用。当我们在导入Spring源码时,如果没有这些jar包...
总的来说,深入分析Spring框架的源代码,能够帮助我们理解其设计思想和实现原理,从而在实际开发中更好地利用这些功能。同时,这也有助于我们学习和掌握Java面向对象设计原则,以及如何通过模块化和解耦来构建复杂...
它是Spring IoC容器的基础,提供了对bean的实例化、配置、装配和管理的抽象层。 二、BeanFactory的功能 1. **对象的创建**:BeanFactory能够根据配置信息创建bean实例,支持延迟加载(lazy-init),只有在真正需要...