springIOC

xiaoxiao2021-02-28  122

BeanFactory是个Factory,也就是 IOC 容器或对象工厂,所有的 Bean 都是由 BeanFactory( 也就是 IOC 容器 ) 来进行管理。

FactoryBean是一个能生产或者修饰生成对象的工厂Bean,可以在IOC容器中被管理,所以它并不是一个简单的Bean。当使用容器中factory bean的时候,该容器不会返回factory bean本身,而是返回其生成的对象。

   以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。

写的不错

http://www.cnblogs.com/ITtangtang/p/3978349.html

//根据Xml配置文件创建Resource资源对象,该对象中包含了BeanDefinition的信息 ClassPathResource resource =new ClassPathResource("application-context.xml"); //创建DefaultListableBeanFactory DefaultListableBeanFactory factory =new DefaultListableBeanFactory(); //创建XmlBeanDefinitionReader读取器,用于载入BeanDefinition。之所以需要BeanFactory作为参数,是因为会将读取的信息回调配置给factory XmlBeanDefinitionReader reader =new XmlBeanDefinitionReader(factory); //XmlBeanDefinitionReader执行载入BeanDefinition的方法,最后会完成Bean的载入和注册。完成后Bean就成功的放置到IOC容器当中,以后我们就可以从中取得Bean来使用 reader.loadBeanDefinitions(resource);

前一段时候我把Spring技术内幕的关于IOC原理一章看完,感觉代码太多,不好掌握,我特意又各方搜集了一些关于IOC原理的资料,特加深一下印象,以便真正掌握IOC的原理。 IOC的思想是:Spring容器来实现这些相互依赖对象的创建、协调工作。对象只需要关系业务逻辑本身就可以了。 SpringIOC容器的执行步骤是: 1、资源定位,即首先要找到applicationContext.xml文件 2、BeanDefinition的载入,把XML文件中的数据统一加载到BeanDefinition中,方便以后的处理 3、向IOC容器中注入BeanDefinition数据 4、将BeanDefinition中的数据进行依赖注入 IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。 举个现实生活中例子,现在有很多中介公司,例如我爱我家。我爱我家会有各种各样的房源资料,当我们找房子时我们只需把需要的房子告诉我爱我家,我爱我家会根据我们的需求给我们提供适合的房子。这样我们就不用自己去网上、小区广告等各个地方去搜集寻求适合自己的房子,整个过程由我爱我家中介来控制就行了,现在想想有个这个中介是不是使整个过程变得简单愉快了。当然,在实际生活中面对中介我们是需要交中介费的,好比SpringIOC我们也需要维护ApplicationContext这个配置文件,都是成本,面对Spring我们可以忽略成本,哈哈。 下面让我看看SpringIOC的运行过程: 1、首先加载ApplicationContext.xml,资源定位 首先资源定位最终是在Springframe下的AbstractBeanDefinitionReader类中的LoaderBeanDefinitions(String location,Set actualResources) line 98,下面举例说明:

? 1 2 3 4 5 6 <code class = "hljs cs" > public static void main(String[] args) {          ApplicationContext context = new FileSystemXmlApplicationContext(                  "applicationContext.xml" );          User user= (User) context.getBean( "user" );          user.write();      }</code> ? 1 2 3 <code class = "hljs applescript" > <bean class = "com.jader.spring.Model.User" id= "user" >          <property name= "name" value= "jader" >   </property></bean></code> ? 1 2 3 4 5 6 7 8 9 <code class = "hljs cs" > public class User{      private String name;      public void write() {          System.out.println( "my name is:" +name);      }      public void setName(String name) {          this .name = name;      } }</code>

运行程序会输出:my name is jader,很明显,SpringIOC已经把property里的value注入到User的name属性当中。 下面我们来分析Spring是怎么实现的 2、BeanDefinition的载入 载入和解析最终是在Springframework下的AbstractApplicationContext类的refresh()方法实现的,这个方法非常关键,里面包含了资源载入和解析,包括对lazy-init的额外处理等,line 445,下面举例说明: 首先我们定义一个Bean,用来存放Bean拥有的属性

? 1 2 3 4 5 6 <code class = "hljs lasso" >  /* Bean Id */      private String id;      /* Bean Class */      private String type;      /* Bean Property */      private Map<string, object= "" > properties = new HashMap<string, object= "" >();</string,></string,></code>

接下来Spring 就开始加载我们的配置文件了,将我们配置的信息保存在一个HashMap中,HashMap的key就是Bean 的 Id ,HasMap 的value是这个Bean,只有这样我们才能通过context.getBean(“user”)这个方法获得Animal这个类。我们都知道Spirng可以注入基本类型,而且可以注入像List,Map这样的类型,接下来就让我们以Map为例看看Spring是怎么保存的

? 1 2 3 4 5 6 7 8 9 10 11 <code class = "hljs xml" >     <bean class = "BeanMap" id= "beanMap" >          <property name= "myBeanMap" ><map>                  <entry key= "name" >                      <value>jader</value>                  </entry>                  <entry key= "age" >                      <value> 26 </value>                  </entry></map>          </property>      </bean></code>

3、向IOC容器中注册BeanDefinition 注册最终是在Spring frame的DefaultListableBeanFactory类下的registerBeanDefinition(String beanName,BeanDefinition beanDefinition)方法中实现,line 664;下面举例说明:

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <code class = "hljs avrasm" >            if (beanProperty.element( "map" ) != null ) {                      Map<string, object= "" > propertiesMap = new HashMap<string, object= "" >();                      Element propertiesListMap = (Element) beanProperty                              .elements().get( 0 );                      Iterator<!--?--> propertiesIterator = propertiesListMap                              .elements().iterator();                      while (propertiesIterator.hasNext()) {                          Element vet = (Element) propertiesIterator.next();                          if (vet.getName().equals( "entry" )) {                              String key = vet.attributeValue( "key" );                              Iterator<!--?--> valuesIterator = vet.elements()                                      .iterator();                              while (valuesIterator.hasNext()) {                                  Element value = (Element) valuesIterator.next();                                  if (value.getName().equals( "value" )) {                                      propertiesMap.put(key, value.getText());                                  }                                  if (value.getName().equals( "ref" )) {                                      propertiesMap.put(key, new String[] { value                                              .attributeValue( "bean" ) });                                  }                              }                          }                      }                      bean.getProperties().put(name, propertiesMap);                  }</string,></string,></code>

4、依赖注入 SpringIOC的最终依赖注入是是通过AbstractAutowireCapableBeanFactory的doCreateBean(finale String beanName,final RootBeanDefinition mbd,final Object[] args)方法(line 480)的,这个方法里的关键方法有populateBean()和createBeanInstance(),正在实现注入是通过BeanWrapperImpl extends AbstractPropertyAccessor类的setPropertyValue()方法实现 line 911 原理是:通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <code class = "hljs cs" > public static Object newInstance(String className) {          Class<!--?--> cls = null ;          Object obj = null ;          try {              cls = Class.forName(className);              obj = cls.newInstance();          } catch (ClassNotFoundException e) {              throw new RuntimeException(e);          } catch (InstantiationException e) {              throw new RuntimeException(e);          } catch (IllegalAccessException e) {              throw new RuntimeException(e);          }          return obj;      }</code> ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <code class = "hljs cs" > public static void setProperty(Object obj, String name, String value) {          Class<!--? extends Object--> clazz = obj.getClass();          try {              String methodName = returnSetMthodName(name);              Method[] ms = clazz.getMethods();              for (Method m : ms) {                  if (m.getName().equals(methodName)) {                      if (m.getParameterTypes().length == 1 ) {                          Class<!--?--> clazzParameterType = m.getParameterTypes()[ 0 ];                          setFieldValue(clazzParameterType.getName(), value, m,                                  obj);                          break ;                      }                  }              }          } catch (SecurityException e) {              throw new RuntimeException(e);          } catch (IllegalArgumentException e) {              throw new RuntimeException(e);          } catch (IllegalAccessException e) {              throw new RuntimeException(e);          } catch (InvocationTargetException e) {              throw new RuntimeException(e);          } }</code>

最后它将这个类的实例返回给我们,我们就可以用了。我们还是以Map为例看看它是怎么做的,我写的代码里面是创建一个HashMap并把该HashMap注入到需要注入的类中

? 1 2 3 4 5 6 7 8 9 10 11 12 13 <code class = "hljs javascript" >          if (value instanceof Map) {                  Iterator<!--?--> entryIterator = ((Map<!--?, ?-->) value).entrySet()                          .iterator();                  Map<string, object= "" > map = new HashMap<string, object= "" >();                  while (entryIterator.hasNext()) {                      Entry<!--?, ?--> entryMap = (Entry<!--?, ?-->) entryIterator.next();                      if (entryMap.getValue() instanceof String[]) {                          map.put((String) entryMap.getKey(),                                  getBean(((String[]) entryMap.getValue())[ 0 ]));                      }                  }                  BeanProcesser.setProperty(obj, property, map);              }</string,></string,></code>

以上每一步的具体实现我都标注了类名、方法名和行数,大家可以自行查看Spring源码,这里不展示了。 面对Spring技术内幕的第一章介绍SpringIOC原理,难用理解,借助于这边文章可以帮我们理解一下。书读百遍,其义自现,当你读一遍不明白的时候可以反复阅读,这篇文章我都是从网上多方搜集的资料,在这里我表示感谢,希望我们共同进步。

转载请注明原文地址: https://www.6miu.com/read-23970.html

最新回复(0)