debug查看ioc容器结构
@Test public void getHero(){ //创建一个容器,并和配置文件关联(一个容器关联一个配置文件) ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml"); //Object hero0 = ioc.getBean("hero01");//这样获取默认是object,但是编译类型还是Hero,可以强转一下 Hero hero0 = (Hero) ioc.getBean("hero01");//这样获取默认是object,但是编译类型还是Hero,可以强转一下 Hero hero01 = ioc.getBean("hero01", Hero.class);//这种方法制定了class类对象,所以不用转 }
<?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"> <!--解读: 1.beans.xml中可以配置多个bean(一个bean标签表示一个Java对象),这里配置一个hero对象的JavaBean 2.class属性写类的全路径 => 用于spring底层反射创建对象 3.<bean class="com.recorder.spring.bean.Hero" id="hero01"> id表示该bean对象在spring容器中的id,可以通过id获取容器中的对象 4.<property name="id" value="1"></property> value用于给对象的实行赋值 --> <bean class="com.recorder.spring.bean.Hero" id="hero01"> <property name="id" value="1"></property> <property name="name" value="李白"></property> <property name="skill" value="青莲剑歌"></property> </bean> </beans>

这里的ioc是一个重量级的对象,创建比较耗费资源,一般创建一个就可以。
ioc下面的beanFactory就是bean工厂,下面的beanDefinitionMap(类型是ConcurrentHashMap)是一个比较重要的属性
它将我们在beans.xml文件中配置的各个bean的信息保存到了下面的table属性中(只是保留了定义信息,还没有创建成对象),
在debug中可以看到table是一个初始512大小(超过会自动扩容)的ConcurrentHashMap$Node的匿名内部类类型的数组,使用这个内部类是因为方便保存所需要的(对象)信息
不如我们先看一下这个内部类
static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; volatile V val; volatile Node<K,V> next; Node(int hash, K key, V val, Node<K,V> next) { this.hash = hash; this.key = key; this.val = val; this.next = next; } public final K getKey() { return key; } public final V getValue() { return val; } public final int hashCode() { return key.hashCode() ^ val.hashCode(); } public final String toString(){ return key + "=" + val; } public final V setValue(V value) { throw new UnsupportedOperationException(); } public final boolean equals(Object o) { Object k, v, u; Map.Entry<?,?> e; return ((o instanceof Map.Entry) && (k = (e = (Map.Entry<?,?>)o).getKey()) != null && (v = e.getValue()) != null && (k == key || k.equals(key)) && (v == (u = val) || v.equals(u))); } /** * Virtualized support for map.get(); overridden in subclasses. */ Node<K,V> find(int h, Object k) { Node<K,V> e = this; if (k != null) { do { K ek; if (e.hash == h && ((ek = e.key) == k || (ek != null && k.equals(ek)))) return e; } while ((e = e.next) != null); } return null; } }
我们看一下在table中保存的bean信息

可以看到我们在xml文件中配置的各项属性
key就是我们在xml文件中配置的id,
val是GenericBeanDefinition类型的,保存的是配置的对象(hero01)的类(Hero)信息
懒加载就是在使用之前就创建好,非懒加载就是在使用的时候再动态创建
propertyValue就是对象类的各个属性的信息

propertyValue中有一个elementData数组,里面的name就是xml中类的属性的名称,value就是xml中配置的值
刚才看的是保存的类信息,那么容器中创建的对象在哪里呢
我们看到beanFactory中还有一个属性叫singletonObjects(一个单例对象池),创建的对象就在这里,类型依旧是上面看到的内部类
如果在xml中配置的对象是单例的,就会初始化放在table中

我们看一下对象信息,可以看到是和内部类的结构对应的,因为不知道存储的对象类型,所以使用了泛型(V)

当我们执行 ioc.getBean("hero01", Hero.class) 这个getBean方法的时候,会先通过传入的id去beanDefinitionMap中查看是不是一个单例的对象
如果是的话就直接返回这个对象,如果不是就通过反射机制动态地创建一个再返回
另外spring为了方便通过id快速查找,将id也存在了beanFactory下的beanDefinitionNames中,可以通过这个属性快速查看我们地xml中配置了多少个bean

示意图:

本文来自博客园,作者:紫英626,转载请注明原文链接:https://www.cnblogs.com/recorderM/p/16419899.html

浙公网安备 33010602011771号