Spring加载过程图解
Posted 南宫煌_慧
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring加载过程图解相关的知识,希望对你有一定的参考价值。
最近看了一下Spring源码加载的简装版本,为了更好的理解,所以在绘图的基础上,进行了一些总结。(图画是为了理解和便于记忆Spring架构)
Spring的核心是IOC(控制反转)和AOP(面向切面编程),首先我们先一步一步的来了解IOC的实现:
一:首先是第一个模型:Model1:
种子 = BeanDefinition 工厂=BeanFactory
1、此处我们可以看见两个对象 BeanDefinition和BeanFactory,此处把创建对象的权限交给了BeanFactory,现在我们可以看到IOC的雏形,即把创建对象的权利交给了工厂。
public class BeanDefinition { private Object bean; public BeanDefinition(Object bean) { this.bean = bean; } public Object getBean() { return bean; } }
public class BeanFactory { private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(); public Object getBean(String name) { return beanDefinitionMap.get(name).getBean(); } public void registerBeanDefinition(String name, BeanDefinition beanDefinition) { beanDefinitionMap.put(name, beanDefinition); } }
二:接下來我們看第二个模型,对BeanFactory进行扩展
1、此处的BeanDefinition 进行了扩展字段,可以看做是种子有了 3 片叶子,便于记忆,分别是 :
Object -> bean Class ->beanClass String ->beanClassName
2、此处的BeanFactory有了解耦的思想,使用了接口和抽象类
public class BeanDefinition { private Object bean; private Class beanClass; private String beanClassName; public BeanDefinition() { } public void setBean(Object bean) { this.bean = bean; } public Class getBeanClass() { return beanClass; } public void setBeanClass(Class beanClass) { this.beanClass = beanClass; } public String getBeanClassName() { return beanClassName; } public void setBeanClassName(String beanClassName) { this.beanClassName = beanClassName; try { this.beanClass = Class.forName(beanClassName); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public Object getBean() { return bean; } }
public interface BeanFactory { Object getBean(String name); void registerBeanDefinition(String name, BeanDefinition beanDefinition); }
此处 BeanFactory定义了获取Bean 和注册Bean的方法
public abstract class AbstractBeanFactory implements BeanFactory { private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(); @Override public Object getBean(String name) { return beanDefinitionMap.get(name).getBean(); } @Override public void registerBeanDefinition(String name, BeanDefinition beanDefinition) { Object bean = doCreateBean(beanDefinition); beanDefinition.setBean(bean); beanDefinitionMap.put(name, beanDefinition); } /** * 初始化bean * @param beanDefinition * @return */ protected abstract Object doCreateBean(BeanDefinition beanDefinition); }
此处实现了getBean 和registerBean的方法;另外声明了 doCreateBean的抽象方法;
public class AutowireCapableBeanFactory extends AbstractBeanFactory { @Override protected Object doCreateBean(BeanDefinition beanDefinition) { try { Object bean = beanDefinition.getBeanClass().newInstance(); return bean; } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; } }
最后实现类通过反射的方式,创建bean;并注册到工厂里,以便调用。
三:接下来继续完善,查看第三个模型:
1、此处 BeanDefiniton多了一个自定义的属性 propertyValues,便于属性的注入,BeanFactory方法也有所改变
1、BeanDefinition类的定义
public class BeanDefinition { private Object bean; private Class beanClass; private String beanClassName; private PropertyValues propertyValues; public BeanDefinition() { } public void setBean(Object bean) { this.bean = bean; } public Class getBeanClass() { return beanClass; } public void setBeanClass(Class beanClass) { this.beanClass = beanClass; } public String getBeanClassName() { return beanClassName; } public void setBeanClassName(String beanClassName) { this.beanClassName = beanClassName; try { this.beanClass = Class.forName(beanClassName); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public Object getBean() { return bean; } public PropertyValues getPropertyValues() { return propertyValues; } public void setPropertyValues(PropertyValues propertyValues) { this.propertyValues = propertyValues; } }
/** * 用于bean的属性注入 * @author yihua.huang@dianping.com */ public class PropertyValue { private final String name; private final Object value; public PropertyValue(String name, Object value) { this.name = name; this.value = value; } public String getName() { return name; } public Object getValue() { return value; } }
import java.util.ArrayList; import java.util.List; /** * 包装一个对象所有的PropertyValue。<br/> * 为什么封装而不是直接用List?因为可以封装一些操作。 * @author yihua.huang@dianping.com */ public class PropertyValues { private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>(); public PropertyValues() { } public void addPropertyValue(PropertyValue pv) { //TODO:这里可以对于重复propertyName进行判断,直接用list没法做到 this.propertyValueList.add(pv); } public List<PropertyValue> getPropertyValues() { return this.propertyValueList; } }
2、BeanFactory的定义
/** * bean的容器 * @author yihua.huang@dianping.com */ public interface BeanFactory { Object getBean(String name); void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception; }
/** * @author yihua.huang@dianping.com */ public abstract class AbstractBeanFactory implements BeanFactory { private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(); @Override public Object getBean(String name) { return beanDefinitionMap.get(name).getBean(); } @Override public void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception { Object bean = doCreateBean(beanDefinition); beanDefinition.setBean(bean); beanDefinitionMap.put(name, beanDefinition); } /** * 初始化bean * @param beanDefinition * @return */ protected abstract Object doCreateBean(BeanDefinition beanDefinition) throws Exception; }
/** * 可自动装配内容的BeanFactory * * @author yihua.huang@dianping.com */ public class AutowireCapableBeanFactory extends AbstractBeanFactory { @Override protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception { Object bean = createBeanInstance(beanDefinition); applyPropertyValues(bean, beanDefinition); return bean; } protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception { return beanDefinition.getBeanClass().newInstance(); } protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception { for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) { Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName()); declaredField.setAccessible(true); declaredField.set(bean, propertyValue.getValue()); } } }
此处增加了添加 属性的方法 applyPropertyValues;
此模型可概括为:
#1.step1-最基本的容器
*step-1-container-register-and-get*
单纯的map,有get和put bean的功能
# 2.step2-将bean创建放入工厂
*step-2-abstract-beanfactory-and-do-bean-initilizing-in-it*
1. 抽象beanfactory
2. 将bean初始化放入beanfactory
# 2.step3-为bean注入属性
*step-3-inject-bean-with-property*
4、接下来我们来看第四个模型,Spring是如何实现读取配置文件的bean属性的,Model4:
从图中可以看出多了几个模块,现在分别来介绍一下:
1、BD 是简化绘制版的 BeanDefiniton
2、UR 对应下面 IO类,用于读取xml文件
RL 是ResourceLoader,用于配置文件路径
3、BDR 是用来解析XML文件的模块类
4、最后交由BeanFactory创造bean,并提供bean.
1、BeanDefinition
BeanDefiniton
/** * bean的内容及元数据,保存在BeanFactory中,包装bean的实体 * * @author yihua.huang@dianping.com */ public class BeanDefinition { private Object bean; private Class beanClass; private String beanClassName; private PropertyValues propertyValues = new PropertyValues(); public BeanDefinition() { } public void setBean(Object bean) { this.bean = bean; } public Class getBeanClass() { return beanClass; } public void setBeanClass(Class beanClass) { this.beanClass = beanClass; } public String getBeanClassName() { return beanClassName; } public void setBeanClassName(String beanClassName) { this.beanClassName = beanClassName; try { this.beanClass = Class.forName(beanClassName); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public Object getBean() { return bean; } public PropertyValues getPropertyValues() { return propertyValues; } public void setPropertyValues(PropertyValues propertyValues) { this.propertyValues = propertyValues; }
PropertyValue
/** * 用于bean的属性注入 * @author yihua.huang@dianping.com */ public class PropertyValue { private final String name; private final Object value; public PropertyValue(String name, Object value) { this.name = name; this.value = value; } public String getName() { return name; } public Object getValue() { return value; } }
PropertyValues
/** * 包装一个对象所有的PropertyValue。<br/> * 为什么封装而不是直接用List?因为可以封装一些操作。 * @author yihua.huang@dianping.com */ public class PropertyValues { private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>(); public PropertyValues() { } public void addPropertyValue(PropertyValue pv) { //TODO:这里可以对于重复propertyName进行判断,直接用list没法做到 this.propertyValueList.add(pv); } public List<PropertyValue> getPropertyValues() { return this.propertyValueList; } }
2、IO类
Resource
/** * Resource是spring内部定位资源的接口。 * @author yihua.huang@dianping.com */ public interface Resource { InputStream getInputStream() throws IOException; }
/** * @author yihua.huang@dianping.com */ public class UrlResource implements Resource { private final URL url; public UrlResource(URL url) { this.url = url; } @Override public InputStream getInputStream() throws IOException{ URLConnection urlConnection = url.openConnection(); urlConnection.connect(); return urlConnection.getInputStream(); } }
ResourceLoader
/** * @author yihua.huang@dianping.com */ public class ResourceLoader { public Resource getResource(String location){ URL resource = this.getClass().getClassLoader().getResource(location); return new UrlResource(resource); } }
3、BeanDefinitionReader
/** * 从配置中读取BeanDefinitionReader * @author yihua.huang@dianping.com */ public interface BeanDefinitionReader { void loadBeanDefinitions(String location) throws Exception; }
/** * 从配置中读取BeanDefinitionReader * * @author yihua.huang@dianping.com */ public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader { private Map<String,BeanDefinition> registry; private ResourceLoader resourceLoader; protected AbstractBeanDefinitionReader(ResourceLoader resourceLoader) { this.registry = new HashMap<String, BeanDefinition>(); this.resourceLoader = resourceLoader; } public Map<String, BeanDefinition> getRegistry() { return registry; } public ResourceLoader getResourceLoader() { return resourceLoader; } }
XmlBeanDefinitionReader
/** * @author yihua.huang@dianping.com */ public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { public XmlBeanDefinitionReader(ResourceLoader resourceLoader) { super(resourceLoader); } @Override public void loadBeanDefinitions(String location) throws Exception { InputStream inputStream = getResourceLoader().getResource(location).getInputStream(); doLoadBeanDefinitions(inputStream); } protected void doLoadBeanDefinitions(InputStream inputStream) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = factory.newDocumentBuilder(); Document doc = docBuilder.parse(inputStream); // 解析bean registerBeanDefinitions(doc); inputStream.close(); } public void registerBeanDefinitions(Document doc) { Element root = doc.getDocumentElement(); parseBeanDefinitions(root); } protected void parseBeanDefinitions(Element root) { NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; processBeanDefinition(ele); } } } protected void processBeanDefinition(Element ele) { String name = ele.getAttribute("name"); String className = ele.getAttribute("class"); BeanDefinition beanDefinition = new BeanDefinition(); processProperty(ele,beanDefinition); beanDefinition.setBeanClassName(className); getRegistry().put(name, beanDefinition); } private void processProperty(Element ele,BeanDefinition beanDefinition) { NodeList propertyNode = ele.getElementsByTagName("property"); for (int i = 0; i < propertyNode.getLength(); i++) { Node node = propertyNode.item(i); if (node instanceof Element) { Element propertyEle = (Element) node; String name = propertyEle.getAttribute("name"); String value = propertyEle.getAttribute("value"); beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name,value)); } } } }
此文件用来定义文名,并解析xml文件
未完,待续 。。。。。。
以上是关于Spring加载过程图解的主要内容,如果未能解决你的问题,请参考以下文章
《Java虚拟机原理图解》5. JVM类加载器机制与类加载过程