BeanDefinition及其实现类

Posted LUPENG

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BeanDefinition及其实现类相关的知识,希望对你有一定的参考价值。

 

目录(?)[+]

 

一、 BeanDefinition及其实现类

BeanDefinition接口

这个接口描述bean的结构,对应XML中的< bean >或者配置类中的@Bean 
它集成了BeanMetadataElement和AttributeAccessor,如下图 
技术分享 
【AttributeAccessor接口】 
类似于map,具有保存和访问name/value属性的能力

public interface AttributeAccessor { 
    void setAttribute(String name, Object value); 
    Object getAttribute(String name); 
    Object removeAttribute(String name); 
    boolean hasAttribute(String name); 
    String[] attributeNames(); 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

【BeanMetadataElement接口】 
实现此接口的类,访问source(配置源)的能力

public interface BeanMetadataElement { 
    Object getSource(); 
}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

【BeanDefinition接口】 
定义了设置、获取一个BeanDefinition属性方便方法(比如获取scope属性直接使用getScope())

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    //单例或原型
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; 
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

     //Bean角色
    int ROLE_APPLICATION = 0; 
    int ROLE_SUPPORT = 1; 
    int ROLE_INFRASTRUCTURE = 2;

    // 返回/设置父BeanDefinition 
    String getParentName(); 
    void setParentName(String parentName);

    //返回/设置 当前的BeanClassName(不等于最终Bean的名称)
    String getBeanClassName(); 
    void setBeanClassName(String beanClassName);

    //返回设置 factory bean name  
    String getFactoryBeanName(); 
    void setFactoryBeanName(String factoryBeanName);

    String getFactoryMethodName(); 
    void setFactoryMethodName(String factoryMethodName);

    String getScope(); 
    void setScope(String scope);

    boolean isLazyInit(); 
    void setLazyInit(boolean lazyInit);

    String[] getDependsOn(); 
    void setDependsOn(String... dependsOn);

    boolean isAutowireCandidate(); 
    void setAutowireCandidate(boolean autowireCandidate);

    boolean isPrimary(); 
    void setPrimary(boolean primary);

    ConstructorArgumentValues getConstructorArgumentValues();

    MutablePropertyValues getPropertyValues(); 
    boolean isSingleton(); 
    boolean isPrototype(); 
    boolean isAbstract(); 
    int getRole(); 
    String getDescription(); 
    String getResourceDescription(); 
    BeanDefinition getOriginatingBeanDefinition();

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

BeanDefinition的子接口和实现类

技术分享

【AnnotatedBeanDefinition 接口】

这个接口可以获取BeanDefinition注解相关数据

public interface AnnotatedBeanDefinition extends BeanDefinition { 
    AnnotationMetadata getMetadata(); 
    MethodMetadata getFactoryMethodMetadata(); 
}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

【AbstractBeanDefinition】

这个抽象类的构造方法设置了BeanDefinition的默认属性,重写了equals,hashCode,toString方法。

【ChildBeanDefinition】

可以从父BeanDefinition中集成构造方法,属性等

【RootBeanDefinition】

代表一个从配置源(XML,Java Config等)中生成的BeanDefinition

GenericBeanDefinition

GenericBeanDefinition是自2.5以后新加入的bean文件配置属性定义类,是ChildBeanDefinition和RootBeanDefinition更好的替代者

【AnnotatedGenericBeanDefinition】

对应注解@Bean

@Component("t")
public class Tester {
    public static void main(String[] args) throws Exception {
        AnnotatedGenericBeanDefinition beanDefinition=new AnnotatedGenericBeanDefinition(Tester.class);
        System.out.println(beanDefinition.getMetadata().getAnnotationTypes());
        System.out.println(beanDefinition.isSingleton());
        System.out.println(beanDefinition.getBeanClassName()); 
    }
}

==========输出==============
[org.springframework.stereotype.Component]
true
Tester
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

二 、BeanDefinitionHolder

BeanDefinitionHolder

持有一个BeanDefinition,名称,和别名数组。在spring内部,它用来临时保存BeanDefinition来传递BeanDefinition。 
它的部分方法如下:

public class BeanDefinitionHolder implements BeanMetadataElement {

    private final BeanDefinition beanDefinition;
    private final String beanName;
    private final String[] aliases; 

    public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, String[] aliases) {
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        Assert.notNull(beanName, "Bean name must not be null");
        this.beanDefinition = beanDefinition;
        this.beanName = beanName;
        this.aliases = aliases;
    }  
    public BeanDefinition getBeanDefinition() {
        return this.beanDefinition;
    } 
    public String getBeanName() {
        return this.beanName;
    } 
    public String[] getAliases() {
        return this.aliases;
    }
    //其他方法...省略
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

三、BeanDefinitionRegistry接口

这个接口定义了‘注册/获取BeanDefinition’的方法 。 
接口定义:

public interface BeanDefinitionRegistry extends AliasRegistry {
    //注册一个BeanDefinition  
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException; 
    //根据name,从自己持有的多个BeanDefinition 中 移除一个 
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    // 获取某个BeanDefinition
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; 
    boolean containsBeanDefinition(String beanName);//是否包含 
    String[] getBeanDefinitionNames();//获取所有名称 
    int getBeanDefinitionCount();//获取持有的BeanDefinition数量 
    boolean isBeanNameInUse(String beanName); //判断某个BeanDefinition是否在使用
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

实现类一般使用Map保存多个BeanDefinition,如下:

Map<String, BeanDefinition> beanDefinitionMap = new HashMap<String, BeanDefinition>();
  • 1
  • 1

实现类有SimpleBeanDefinitionRegistry,DefaultListableBeanFactoryGenericApplicationContext等。

SimpleBeanDefinitionRegistry

SimpleBeanDefinitionRegistry是最基本的实现类。 
使用:

public static void main(String[] args) throws Exception {

    //实例化SimpleBeanDefinitionRegistry
    SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();

    //注册两个BeanDefinition
    BeanDefinition definition_1 = new GenericBeanDefinition();
    registry.registerBeanDefinition("d1", definition_1);

    BeanDefinition definition_2 = new RootBeanDefinition();
    registry.registerBeanDefinition("d2", definition_2);

    //方法测试
    System.out.println(registry.containsBeanDefinition("d1"));//true
    System.out.println(registry.getBeanDefinitionCount());//2
    System.out.println(Arrays.toString(registry.getBeanDefinitionNames()));//[d1, d2] 
}

================结果==================
true
2
[d1, d2]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

四、BeanDefinitionReader接口

BeanDefinitionRegistry接口一次只能注册一个BeanDefinition,而且只能自己构造BeanDefinition类来注册。BeanDefinitionReader解决了这些问题,它一般可以使用一个BeanDefinitionRegistry构造,然后通过#loadBeanDefinitions(..)等方法,把“配置源”转化为多个BeanDefinition并注册到BeanDefinitionRegistry中 。 
可以说BeanDefinitionReader帮助BeanDefinitionRegistry实现了高效、方便的注册BeanDefinition。

BeanDefinitionReader接口定义如下:

public interface BeanDefinitionReader {
    //获取BeanDefinitionRegistry 
    BeanDefinitionRegistry getRegistry();

    ResourceLoader getResourceLoader();

    ClassLoader getBeanClassLoader(); 

    //获取Bean的名称生成器
    BeanNameGenerator getBeanNameGenerator();

    //载入BeanDefinition
    int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;

     //载入BeanDefinition
    int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;

     //载入BeanDefinition
    int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;

     //载入BeanDefinition
    int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

类的体系结构

技术分享

AbstractBeanDefinitionReader:实现了EnvironmentCapable,提供了获取/设置环境的方法。定义了一些通用方法,使用策略模式,将一些具体方法放到子类实现。 
XmlBeanDefinitionReader:读取XML文件定义的BeanDefinition 
PropertiesBeanDefinitionReader:可以从属性文件,Resource,Property对象等读取BeanDefinition 
GroovyBeanDefinitionReader:可以读取Groovy语言定义的Bean

实现类:XmlBeanDefinitionReader

把xml配置文件转化成beanDefinition

这个类就不做演示了
  • 1
  • 1

实现类: PropertiesBeanDefinitionReader

可以从Properties文件读取BeanDefinition,文件可以是如下结构:

#bean名称.(属性)=值
==========================
mybean.(class)=PropertyReaderTest
mybean.(abstract)=true 
mybean.(lazy-init)=true
mybean.(scope)=prototype    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

程序实例:

public class PropertyReaderTest {
    public static void main(String[] args) {
        //定义BeanDefinitionRegistry 
        BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); 
        //使用BeanDefinitionRegistry实例 构造BeanDefinitionReader
        PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(registry);
        //载入文件
        reader.loadBeanDefinitions("config.properties");

        System.out.println(registry.getBeanDefinition("mybean"));
    }
} 

================输出=================
.......//日志信息 略
Generic bean: class [PropertyReaderTest]; scope=prototype; abstract=true; lazyInit=true; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

五、读取注解定义的BeanDefinition

注解相关的BeanDefinitionReader并没有实现BeanDefinitionReader接口,有如下类:

AnnotatedBeanDefinitionReader类

使用如下:

SimpleBeanDefinitionRegistry registry= new SimpleBeanDefinitionRegistry();
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);
reader.register(Tester.class);
System.out.println( registry.getBeanDefinitionCount());

=========================
7 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

我们只注册了一个Bean,为什么出现7个呢?原来是AnnotatedBeanDefinitionReader 向BeanDefinitionRegistry自动注册了6个BeanDefinition。这个在以后章节中详解。

ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner 继承自ClassPathScanningCandidateComponentProvider 
类结构如下: 
技术分享

【ClassPathScanningCandidateComponentProvider】 
这个类的findCandidateComponents可以扫描到@Component @Repository @Service @Controller 的BeanDefinition,并加入Set 集合中

ClassPathScanningCandidateComponentProvider provider=new ClassPathScanningCandidateComponentProvider(true); 
Set<BeanDefinition> definitionSet= provider.findCandidateComponents("com.jazz.web");
System.out.println(definitionSet.size());
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

【ClassPathBeanDefinitionScanner】

这里写代码片
















以上是关于BeanDefinition及其实现类的主要内容,如果未能解决你的问题,请参考以下文章

BeanDefinition源码解析

Spring IOC BeanDefinition解析

Spring IOC容器的初始化-BeanDefinition的注册

BeanDefinition 解析流程解析所有配置类

springIOC源码解析之BeanDefinition的注册

二Spring组装BeanDefinition详情