通过tiny-spring学习Spring框架IOC源码(四)

这篇文章继续跟随tiny-spring的思路体会Spring框架中IOC中的经典设计,第五步主要将Xml中配置的Bean解析后注入到Bean实例中后,引入了BeanReference,并getBean时候判断没有bean的时候创建新的实例,第六步是使用ApplicationContext将BeanFactory作为属性后,后续可以使用组合的方式对bean的功能进行增强和扩展。

一、BeanReference-保存对Bean的引用

1.首先定义BeanReference的类

@Data
public class BeanReference {
    private String name;
    private Object bean;
}

2.修改获取bean的value

private void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exception {
        for (PropertyValue propertyValue : beanDefinition.getPropertyValues().getPropertyValueList()) {
            Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());
            declaredField.setAccessible(true);
            Object value = propertyValue.getValue();
            if (value instanceof BeanReference) {
                BeanReference beanReference = (BeanReference) value;
                value = getBean(beanReference.getName());
            }
            declaredField.set(bean, value);
        }
    }

二、lazy初始化-getBean()中调用createBean()

public void initLazyBean() throws Exception {
        Iterator it = beanDefinitionNames.iterator();
        while (it.hasNext()) {
            String beanName = (String) it.next();
            getBean(beanName);
        }
    }

三、测试

@Test
    public void testLazyInitBean() throws Exception {
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
        xmlBeanDefinitionReader.loadBeanDefinition("springioc.xml");
        AbstractBeanFactory beanFactory = new AutowireCapableBeanFactory();
        for(Map.Entry<String, BeanDefinition> beanDefinitionEntry : xmlBeanDefinitionReader.getRegistry().entrySet()) {
            beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
        }
        beanFactory.initLazyBean();
        HelloSpringIOCService helloSpringIOCService = (HelloSpringIOCService) beanFactory.getBean("helloSpringIOCService");
        helloSpringIOCService.helloSpring();
    }

四、ApplicationContext引入

1.引入ApplicationContext作用是包装bean的初始化流程,对应用透明,使用组合方式优于继承更加方便扩展,首先定义ApplicationContext接口
public interface ApplicationContext extends BeanFactory {
}
2.抽象类AbstractApplicationContext实现ApplicationContext接口,包装beanFactory,定义初始化流程的refresh()方法
public abstract class AbstractApplicationContext implements ApplicationContext {

    protected AbstractBeanFactory beanFactory;

    AbstractApplicationContext(AbstractBeanFactory beanFactory){
        this.beanFactory = beanFactory;
    }

    public void refresh() throws Exception {
    }

    @Override
    public Object getBean(String name) throws Exception {
        return beanFactory.getBean(name);
    }
}
3.实现类XmlClassPathApplicationContext中实现refresh()方法,完成bean的初始化过程

public class XmlClassPathApplicationContext extends AbstractApplicationContext {

    private String configLocation;

    public XmlClassPathApplicationContext(String configLocation) throws Exception {
        this(configLocation, new AutowireCapableBeanFactory());
    }

    public XmlClassPathApplicationContext(String configLocation, AbstractBeanFactory beanFactory) throws Exception {
        super(beanFactory);
        this.configLocation = configLocation;
        refresh();
    }

    @Override
    public void refresh() throws Exception {
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader());
        xmlBeanDefinitionReader.loadBeanDefinition(configLocation);
        Map<String, BeanDefinition> registry = xmlBeanDefinitionReader.getRegistry();
        for (Map.Entry<String, BeanDefinition> beanDefinitionEntry : registry.entrySet()) {
            beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
        }
    }
}

五、测试

对于ApplicationContext测试后,Spring整个IOC过程就完成了
public class ApplicationContextTest {
    @Test
    public void testApplicationContext() throws Exception {
        ApplicationContext applicationContext = new XmlClassPathApplicationContext("springioc.xml");
        HelloSpringIOCService helloSpringIOCService = (HelloSpringIOCService) applicationContext.getBean("helloSpringIOCService");
        helloSpringIOCService.helloSpring();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值