这篇文章继续跟随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接口
3.实现类XmlClassPathApplicationContext中实现refresh()方法,完成bean的初始化过程
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);
}
}
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();
}
}