BeanInfo
xml文件对应的类,一个BenInfo代表一个bean,即一个对象
private String className;//类的全限定名
private String objectName;//名(byName找)
private String scope;//模式,比如单例模式single
private List<String> properties;//如果是引用类型的话会有这个
private List<String> values;//引用类型属性初始值
HandleBeanInfo(final类,不可更改)—解析xml
- 属性里存两套HashMap一个beansInfoMaps<String, BeanInfo>用来存解析后xml文件,一个activebeansMaps<String, Object>存创建后的对象
- 静态代码块解析:首先拿到文件的绝对路径(不要硬编码,经典代码)
String path=HandleBeansInfo.class.getClassLoader().getResource("").toString().substring(6);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new File(path+"com/yqc/spring/beans.xml"));
- 调用getRootElement()拿到根节点,调getChildren()拿到所有孩子
- 循环去解析
- 调getAttribute()拿到class(如果没拿到 直接结束 ,不多赘述)
问题:如果拿不到class怎么办<==>xml没写class
答:最少要有class,没有class就没办法解析,没办法装配 - 创建BeanInfo对象,className赋值class
- 判断scope能不能拿到,拿到直接set,否则set(“single”)单例模式
- 判断name能不能拿到,拿到直接set,否则set为类首字符小写的格式
- 拿到所有孩子,如果拿不到直接给HashMap调put(bean.getObjectName(),bean)然后结束
- 走到这里说明是有属性的类,开两个List,循环赋值
- 每一轮循环都getAttribute("")有name,value或者ref
这里要标识一下是value还是ref,就给ref前面街上"ref:"
- 记得都给beanInfo的属性set进去
- 最后put(bean.getObjectName(),bean)到HashMap里头
第8点和put方法的时候都用到了getObjectName()的方法,这个方法就是自己定义的static方法,里面把全限定名的最后一个’.'后头的名字(类名)取出来转成字符数组,第一个字符转成小写,再返回字符串
SpringCore<–>用来实现容器托管的类
两个静态方法一个是getBean一个是创建对象createObject
- public static Object getBean(String name)
- 调上面的第一种beansInfoMaps.get(Name)去得到xml解析好的beanInfo
- 调第二种activebeansMaps.get(Name)去得到已经创建好的对象object
- 判断2是否能得到对象object
- 如果得到,判断1解析出来的beanInfo.getScope()是否是单例(single)
- 如果是,就直接返回object
- 如果不是,调用createObject(BeanInfo beanInfo)方法创建对象
- 把对象放到activebeansMaps里面
- 把对象返回
- 如果没得到object, 调用createObject(BeanInfo beanInfo)方法创建对象
- 把对象放到activebeansMaps里面
- 把对象返回
注意:把对象放到activebeansMaps里面是用put方法,如果是单例模式就用replace方法,因为只有一个实例
- private static Object createObject(BeanInfo beanInfo)
- 老一套,getClassName()拿到类的全限定名,forName()拿到字节码对象,newInstance()拿到对象object
- 创建List调用beanInfo.getProperties()拿到所有属性
注意:如果没有成员变量,这里就拿不到,就不进入循环,就到最后返回object就好了
- 循环赋值:getDeclaredField(fieldName)拿到属性
- 打开权限准备赋值,如果value包含ref那就说明是属性引用类型,就调用getBean()方法(递归)得到之后set就可
- 如果是Integer/String等等之类的,就if/else if/else if判断就好,然后set赋值
- 结束循环后,返回object
xml文件样本
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean class="com.yqc.Demo" scope="session"/>
<bean name="login" class="com.yqc.Login" scope="request"/>
<bean name="check" class="com.yqc.Check" scope="single">
<property name="msg" value="china"/>
<property name="dao" ref="mydao"/>
</bean>
<bean name="hello" class="com.yqc.test.Hello" scope="single">
<property name="msg" value="china"/>
<!-- <property name="dao" ref="mydao"/> -->
</bean>
</beans>