Spring IOC 之 xml配置解析过程(BeanDefinition)源码

1、首先从简单使用开始

spring 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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
    >

   <bean id ="person" class="org.spring.Person">
      <property name="name" value="zhangsan"></property>
   </bean>

</beans>

java 代码:

public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

测试代码:

ClassPathResource resource = new ClassPathResource("spring-ioc.xml");
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions(resource);

Person person = beanFactory.getBean(Person.class);
System.out.println(person);

运行结果:

=======================从源码层面简单分析一下逻辑===================

一个简单的Bean工厂实现有以下几个步骤:
  • 步骤1:创建BeanFactory工厂类,用来缓存生成的BeanDefinition和bean实例
  • 步骤2:创建XmlBeanDefinitionReader类,解析xml资源,创建Document对象
  • 步骤3:创建BeanDefinitionDocumentReader类,解析Document对象
  • 步骤4:创建BeanDefinitionParserDelegate类, 专门解析<bean>元素的Element对象以及自定义标签元素(例如:<dubbo:server> <dubbo:service>),自定义标签解析任务会委托给NamespaceHandler处理
  • 步骤5: 创建NamespaceHandler类,处理自定义的命名空间;创建BeanDefinitionParser类,处理自定义的标签元素
===========根据上面步骤自己实现一版简化版的Bean工厂容器===================
准备阶段:

1、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:dubbo="http://www.myspringtest.org/schema/dubbo/spring-dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	   http://www.myspringtest.org/schema/dubbo/spring-dubbo http://www.myspringtest.org/schema/dubbo/spring-dubbo.xsd">

    <bean id="person" class="org.spring.xml.bean.Person">
        <property name="name" value="zhangsan"></property>
    </bean>

    <dubbo:server url="http://localhost" port="8080"></dubbo:server>
    <dubbo:service serviceName="Login" methodName="auth"></dubbo:service>
</beans>

2、准备三个bean类

public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Server {
    private String url;
    private String port;

    public void setUrl(String url) {
        this.url = url;
    }

    public void setPort(String port) {
        this.port = port;
    }
}
public class Service {
    private String serviceName;
    private String methodName;

    public String getServiceName() {
        return serviceName;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
}

编码阶段:

1、定义一个简化版的BeanDefinition,<bean>元素解析后的内容都被封装成BeanDefinition

public class BeanDefinition {

    //装载bean的Class
    private Class<?> beanClass;

    //装载bean的属性名称和属性值,简单起见仅支持String类型字段
    //在spring IOC中用MutablePropertyValues装载属性
    private Map<String, Object> propertyValueMap =  new HashMap<String, Object>(0);

    public void setBeanClass(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    public Class<?> getBeanClass() throws IllegalStateException {
        return this.beanClass;
    }

    public void addPropertyValue(String name, Object value) {
        propertyValueMap.put(name, value);
    }

    public Map<String, Object> getPropertyValueMap() {
        return propertyValueMap;
    }
}

2、便于程序处理,定义一个BeanDefinition携带者类==》BeanDefinitionHolder

public class BeanDefinitionHolder {
    //装载bean的定义信息
    private final BeanDefinition beanDefinition;

    //bean的名称
    private final String beanName;


    public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName) {
        this.beanDefinition = beanDefinition;
        this.beanName = beanName;
    }

    public BeanDefinition getBeanDefinition() {
        return beanDefinition;
    }

    public String getBeanName() {
        return beanName;
    }
}

3、定义一个BeanDefinitionRegistry接口,用于注册BeanDefinition

public interface BeanDefinitionRegistry {

    //注册beanDefinition
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}

4、定义一个简单的Bean工厂类:SimpleBeanFactory,用来缓存BeanDefinition、创建Bean实例以及缓存生成的单例Bean实例

public class SimpleBeanFactory implements BeanDefinitionRegistry {

    //用来缓存生成的beanDefinition
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

    //用来缓存生成的bean实例
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

    //---------------------------------------------------------------------
    // Implementation of BeanDefinitionRegistry interface
    //---------------------------------------------------------------------
    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }

    //获取bean对象,简单模拟创建bean的过程
    public Object getBean(String beanName) {
        if(singletonObjects.containsKey(beanName)) {
            return singletonObjects.get(beanName);
        } else {
            if(beanDefinitionMap.containsKey(beanName)) {
                BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
                Class<?> beanClass = beanDefinition.getBeanClass();
                try {
                    //实例化bean对象
                    O
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值