Spring Boot【原理分析】(3)——BeanDefinition
来源:互联网 发布:淘宝hot怎么收费 编辑:程序博客网 时间:2024/05/22 00:35
一、简介
BeanDefinition描述了一个Bean的实例,包括属性,构造方法参数,注解等更多信息。为后面实例化Bean提供元数据依据。
BeanDefinition的实现类有:
1. RootBeanDefinition:spring BeanFactory运行期里,内部特殊bean的定义。
2. ConfigurationClassBeanDefinition:继承RootBeanDefinition,ConfigurationClassBeanDefinitionReader内部静态类。上文(2)中提到的Configuration Class内定义的Bean被解析成这个BeanDefinition。
3. ChildBeanDefinition:Spring2.5后弃用。
4. GenericBeanDefinition:@EnableConfigurationProperties和Spring显示创建。@ImportResource
5. ScannedGenericBeanDefinition:上文(2)中提到的ComponentScanAnnotationParser扫描的@Component定义被解析成这个BeanDefinition。
6. AnnotatedGenericBeanDefinition:Spring Boot autoconfigure功能spring.facotries中定义的EnableAutoConfiguration,以及内部子Configuration。@Import
二、创建过程
1.GenericBeanDefinition:
这里主要看一下@ImportResource xml中定义的bean。
ConfigurationClassBeanDefinitionReader解析Configuration Class时会解析ImportResource,XmlBeanDefinitionReader具体解析xml中的Beans,最终由BeanDefinitionParserDelegate解析每个Bean:
public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } //构建GenericBeanDefinition并设置className和parentName AbstractBeanDefinition bd = createBeanDefinition(className, parent); //对scope、abstract、lazy-init、autowire、dependency-check、depends-on、autowire-candidate、primary、init-method、destroy-method、factory-method、factory-bean属性进行解析。 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); //解析meta数据,用于注入。<meta key="format" value="BLURAY"/> parseMetaElements(ele, bd); //解析lookup-method数据,用于abstract方法动态生产bean。<lookup-method name="createCommand" bean="myCommand"/> parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); /** * 解析replaced-method数据,用于根据参数类型替换方法。 * <replaced-method name="computeValue" replacer="replacementComputeValue"> * <arg-type>String</arg-type> * </replaced-method> **/ parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); // 解析constructor-arg,构造函数参数。可以index,type,name匹配。 parseConstructorArgElements(ele, bd); // 解析property数据,用于属性赋值或注入。<property name="driverClassName" value="com.mysql.jdbc.Driver"/> parsePropertyElements(ele, bd); /** * 解析qualifier数据,用于注入,和meta类似。 * <qualifier type="MovieQualifier"> * <attribute key="format" value="VHS"/> * <attribute key="genre" value="Action"/> * </qualifier> **/ parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } catch (ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } catch (NoClassDefFoundError err) { error("Class that bean class [" + className + "] depends on not found", ele, err); } catch (Throwable ex) { error("Unexpected failure during bean definition parsing", ele, ex); } finally { this.parseState.pop(); } return null;}
解析完基本BeanDefinition后,需要调用decorateBeanDefinitionIfRequired
对NameSpace属性进行解析如p:name=”test”。
到此定义在xml中Bean解析成GenericBeanDefinition完成。
2.ScannedGenericBeanDefinition
ScannedGenericBeanDefinition通过扫描Component,再通过MetadataReader获取AnnotationMetadata构建。重点关注MetadataReader的获取。
MetadataReader直接通过构造函数构建:
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException { InputStream is = new BufferedInputStream(resource.getInputStream()); ClassReader classReader; try { classReader = new ClassReader(is); } catch (IllegalArgumentException ex) { throw new NestedIOException("ASM ClassReader failed to parse class file - " + "probably due to a new Java class file version that isn't supported yet: " + resource, ex); } finally { is.close(); } AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader); classReader.accept(visitor, ClassReader.SKIP_DEBUG); this.annotationMetadata = visitor; // (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor) this.classMetadata = visitor; this.resource = resource;}
从源码可以看出, annotationMetadata 直接直接通过读取java class文件获取信息,后面bean的创建,就使用了这个annotationMetadata 。
3.ConfigurationClassBeanDefinition
ConfigurationClassBeanDefinition是定义在Configuration Class中的Bean,在这个bean创建是需要调用到Configuration Class中定义bean的方法。所以这个BeanDefinition的重点(特殊点)在于factoryMethodMetadata,即Configuration Class的对应的MethodMetaData。再通过解析Bean注解和Scope注解设置相应的值。
4.AnnotatedGenericBeanDefinition
@Import中定义的Bean,是作为Configuration Class来进行解析的,在ConfigurationClassParser
时已经解析成一个Configuration Class,并生成了metadata。后续和Component生成ScannedGenericBeanDefinition类似。spring.facotries中的EnableAutoConfiguration也是在ConfigurationClassParser的时候扫描得到Configuration Class。
5.ConfigurationClass
上面几个BeanDefinition创建是需要用的ConfigurationClass, ConfigurationClass是何时创建的,怎么创建的?
ConfigurationClassParser中创建ConfigurationClass源码:
protected final void parse(String className, String beanName) throws IOException { MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className); processConfigurationClass(new ConfigurationClass(reader, beanName));}protected final void parse(Class<?> clazz, String beanName) throws IOException { processConfigurationClass(new ConfigurationClass(clazz, beanName));}protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException { processConfigurationClass(new ConfigurationClass(metadata, beanName));}public ConfigurationClass asConfigClass(ConfigurationClass importedBy) throws IOException { if (this.source instanceof Class<?>) { return new ConfigurationClass((Class<?>) this.source, importedBy); } return new ConfigurationClass((MetadataReader) this.source, importedBy);}
第一个是在递归解析Component时创建。最后一个是在解析内部成员类和Import类。
6.getMergedBeanDefinition
在构建Bean实例是,都会获取MergedBeanDefinition,这个功能是把所有不是RootBeanDefinition实例的转成RootBeanDefinition,进行统一调用。
- Spring Boot【原理分析】(3)——BeanDefinition
- Spring Boot【原理分析】(1)——SpringApplication
- Spring Boot【原理分析】(2)——ApplicationContext
- Spring Boot【原理分析】(4)——ConfigurationClassEnhancer
- spring源代码分析(3):关于BeanDefinition的思考
- spring源代码分析(3):关于BeanDefinition的思考
- spring boot启动原理分析
- spring boot 启动原理分析
- Spring框架之基础类—BeanDefinition接口
- spring beandefinition
- spring BeanDefinition
- 【Spring Boot】spring boot应用启动原理分析
- spring boot应用启动原理分析
- spring boot应用启动原理分析
- spring boot应用启动原理分析
- Spring Boot实战与原理分析
- spring boot应用启动原理分析
- spring boot应用启动原理分析
- Android 清单文件小结以及AS编译版本
- inputType参数类型说明
- JS的DOM操作元素示例1--删除添加元素
- javaweb-浏览器根据搜索条件从服务器导出/导入excel到本地
- android实现监听打电话并录音保存到本地
- Spring Boot【原理分析】(3)——BeanDefinition
- version of spring facet could not be detected.see error log for details.解决方案
- 记一次断电后solr重启异常
- Block 其实很简单的
- centos:sshd 服务操作
- gstreamer学习笔记:将音视频合成MPEG2-TS流并打包通过rtp传输
- 2017书单
- HTTP协议6-HTTP内容类型
- JSP 学习笔记(1) -- 基础内容总结