使用 BeanDefinition 描述 Spring Bean
什么是beandefinition
在java中,一切皆对象。在jdk中使用java.lang.class
来描述类
这个对象。
在spring中,存在bean
这样一个概念,那spring又是怎么抽象bean
这个概念,用什么类来描述bean
这个对象呢?spring使用beandefinition
来描述bean
。
beandefinition
beandefinition
继承了attributeaccessor
和beanmetadataelement
接口。在spring中充斥着大量的各种接口,每种接口都拥有不同的能力,某个类实现了某个接口,也就相应的拥有了某种能力。
attributeaccessor
顾名思义,这是一个属性访问者,它提供了访问属性的能力。
beanmetadataelement
beanmetadataelement
中只有一个方法,用来获取元数据元素的配置源对象:
public interface beanmetadataelement { @nullable object getsource(); }
beandefinition
beandefinition
接口是spring对bean
的抽象。
我们可以从源码中可以看出,spring是怎么描述一个bean
:
public interface beandefinition extends attributeaccessor, beanmetadataelement { /** * scope identifier for the standard singleton scope: "singleton". * <p>note that extended bean factories might support further scopes. * * @see #setscope */ string scope_singleton = configurablebeanfactory.scope_singleton; /** * scope identifier for the standard prototype scope: "prototype". * <p>note that extended bean factories might support further scopes. * * @see #setscope */ string scope_prototype = configurablebeanfactory.scope_prototype; /** * role hint indicating that a {@code beandefinition} is a major part * of the application. typically corresponds to a user-defined bean. */ int role_application = 0; /** * role hint indicating that a {@code beandefinition} is a supporting * part of some larger configuration, typically an outer * {@link org.springframework.beans.factory.parsing.componentdefinition}. * {@code support} beans are considered important enough to be aware * of when looking more closely at a particular * {@link org.springframework.beans.factory.parsing.componentdefinition}, * but not when looking at the overall configuration of an application. */ int role_support = 1; /** * role hint indicating that a {@code beandefinition} is providing an * entirely background role and has no relevance to the end-user. this hint is * used when registering beans that are completely part of the internal workings * of a {@link org.springframework.beans.factory.parsing.componentdefinition}. */ int role_infrastructure = 2; // modifiable attributes /** * set the name of the parent definition of this bean definition, if any. */ void setparentname(@nullable string parentname); /** * return the name of the parent definition of this bean definition, if any. */ @nullable string getparentname(); /** * specify the bean class name of this bean definition. * <p>the class name can be modified during bean factory post-processing, * typically replacing the original class name with a parsed variant of it. * * @see #setparentname * @see #setfactorybeanname * @see #setfactorymethodname */ void setbeanclassname(@nullable string beanclassname); /** * return the current bean class name of this bean definition. * <p>note that this does not have to be the actual class name used at runtime, in * case of a child definition overriding/inheriting the class name from its parent. * also, this may just be the class that a factory method is called on, or it may * even be empty in case of a factory bean reference that a method is called on. * hence, do <i>not</i> consider this to be the definitive bean type at runtime but * rather only use it for parsing purposes at the individual bean definition level. * * @see #getparentname() * @see #getfactorybeanname() * @see #getfactorymethodname() */ @nullable string getbeanclassname(); /** * override the target scope of this bean, specifying a new scope name. * * @see #scope_singleton * @see #scope_prototype */ void setscope(@nullable string scope); /** * return the name of the current target scope for this bean, * or {@code null} if not known yet. */ @nullable string getscope(); /** * set whether this bean should be lazily initialized. * <p>if {@code false}, the bean will get instantiated on startup by bean * factories that perform eager initialization of singletons. */ void setlazyinit(boolean lazyinit); /** * return whether this bean should be lazily initialized, i.e. not * eagerly instantiated on startup. only applicable to a singleton bean. */ boolean islazyinit(); /** * set the names of the beans that this bean depends on being initialized. * the bean factory will guarantee that these beans get initialized first. */ void setdependson(@nullable string... dependson); /** * return the bean names that this bean depends on. */ @nullable string[] getdependson(); /** * set whether this bean is a candidate for getting autowired into some other bean. * <p>note that this flag is designed to only affect type-based autowiring. * it does not affect explicit references by name, which will get resolved even * if the specified bean is not marked as an autowire candidate. as a consequence, * autowiring by name will nevertheless inject a bean if the name matches. */ void setautowirecandidate(boolean autowirecandidate); /** * return whether this bean is a candidate for getting autowired into some other bean. */ boolean isautowirecandidate(); /** * set whether this bean is a primary autowire candidate. * <p>if this value is {@code true} for exactly one bean among multiple * matching candidates, it will serve as a tie-breaker. */ void setprimary(boolean primary); /** * return whether this bean is a primary autowire candidate. */ boolean isprimary(); /** * specify the factory bean to use, if any. * this the name of the bean to call the specified factory method on. * * @see #setfactorymethodname */ void setfactorybeanname(@nullable string factorybeanname); /** * return the factory bean name, if any. */ @nullable string getfactorybeanname(); /** * specify a factory method, if any. this method will be invoked with * constructor arguments, or with no arguments if none are specified. * the method will be invoked on the specified factory bean, if any, * or otherwise as a static method on the local bean class. * * @see #setfactorybeanname * @see #setbeanclassname */ void setfactorymethodname(@nullable string factorymethodname); /** * return a factory method, if any. */ @nullable string getfactorymethodname(); /** * return the constructor argument values for this bean. * <p>the returned instance can be modified during bean factory post-processing. * * @return the constructorargumentvalues object (never {@code null}) */ constructorargumentvalues getconstructorargumentvalues(); /** * return if there are constructor argument values defined for this bean. * * @since 5.0.2 */ default boolean hasconstructorargumentvalues() { return !getconstructorargumentvalues().isempty(); } /** * return the property values to be applied to a new instance of the bean. * <p>the returned instance can be modified during bean factory post-processing. * * @return the mutablepropertyvalues object (never {@code null}) */ mutablepropertyvalues getpropertyvalues(); /** * return if there are property values values defined for this bean. * * @since 5.0.2 */ default boolean haspropertyvalues() { return !getpropertyvalues().isempty(); } /** * set the name of the initializer method. * * @since 5.1 */ void setinitmethodname(@nullable string initmethodname); /** * return the name of the initializer method. * * @since 5.1 */ @nullable string getinitmethodname(); /** * set the name of the destroy method. * * @since 5.1 */ void setdestroymethodname(@nullable string destroymethodname); /** * return the name of the destroy method. * * @since 5.1 */ @nullable string getdestroymethodname(); /** * set the role hint for this {@code beandefinition}. the role hint * provides the frameworks as well as tools with an indication of * the role and importance of a particular {@code beandefinition}. * * @see #role_application * @see #role_support * @see #role_infrastructure * @since 5.1 */ void setrole(int role); /** * get the role hint for this {@code beandefinition}. the role hint * provides the frameworks as well as tools with an indication of * the role and importance of a particular {@code beandefinition}. * * @see #role_application * @see #role_support * @see #role_infrastructure */ int getrole(); /** * set a human-readable description of this bean definition. * * @since 5.1 */ void setdescription(@nullable string description); /** * return a human-readable description of this bean definition. */ @nullable string getdescription(); // read-only attributes /** * return whether this a <b>singleton</b>, with a single, shared instance * returned on all calls. * * @see #scope_singleton */ boolean issingleton(); /** * return whether this a <b>prototype</b>, with an independent instance * returned for each call. * * @see #scope_prototype * @since 3.0 */ boolean isprototype(); /** * return whether this bean is "abstract", that is, not meant to be instantiated. */ boolean isabstract(); /** * return a description of the resource that this bean definition * came from (for the purpose of showing context in case of errors). */ @nullable string getresourcedescription(); /** * return the originating beandefinition, or {@code null} if none. * allows for retrieving the decorated bean definition, if any. * <p>note that this method returns the immediate originator. iterate through the * originator chain to find the original beandefinition as defined by the user. */ @nullable beandefinition getoriginatingbeandefinition(); }
annotatedbeandefinition
annotatedbeandefinition
继承了beandefinition
,拓展了beandefinition
接口的能力:
beandefinition常见实现类
- childbeandefinition
- rootbeandefinition
- genericbeandefinition
- annotatedgenericbeandefinition
- scannedgenericbeandefinition
beandefinitionbuilder
beandefinitionbuilder
是builder模式的应用。通过这个类我们可以方便的构建beandefinition
的实例对象。举个例子:
@component public class mybeandefinitionregistrypostprocessor implements beandefinitionregistrypostprocessor { @override public void postprocessbeandefinitionregistry(beandefinitionregistry registry) throws beansexception { beandefinition beandefinition = beandefinitionbuilder.genericbeandefinition(orderservice.class) //这里的属性名是根据setter方法 .addpropertyreference("dao", "orderdao") .setinitmethodname("init") .setscope(beandefinition.scope_singleton) .getbeandefinition(); registry.registerbeandefinition("orderservice", beandefinition); } @override public void postprocessbeanfactory(configurablelistablebeanfactory beanfactory) throws beansexception { //do nothing } }
关于beandefinitionregistrypostprocessor
,这里先简单介绍一下,详细的我们后面再说。
beandefinitionregistrypostprocessor
继承了beanfactorypostprocessor
接口,同时又增加了一个新的方法beandefinitionregistrypostprocessor#postprocessbeandefinitionregistry
,该方法允许程序员通过代码编码的方式手动往程序中注册beandefinition
。
实例中的具体程序已上传到github:https://github.com/shenjianeng/spring-code-study
欢迎关注公众号:
上一篇: 童鞋,你能再冷一点么
推荐阅读
-
Spring高级装配,Profile的使用,条件化Bean,解决歧义性
-
使用 BeanDefinition 描述 Spring Bean
-
Spring如何使用xml创建bean对象
-
使用Spring @DependsOn控制bean加载顺序的实例
-
Spring基础使用(一)--------IOC、Bean的XML方式装配
-
Spring Bean的解析 BeanDefinition 与 RuntimeBeanReference
-
Spring(16)——使用注解进行bean定义
-
Spring(18)——使用Java类的形式定义bean(二)
-
Spring使用applicationContext管理bean
-
web过滤器使用spring依赖注入 解决过滤器中不能注入bean的问题