zoukankan      html  css  js  c++  java
  • Spring学习3—控制反转(IOC)Spring依赖注入(DI)和控制反转(IOC)

    一、思想理解
       Spring 能有效地组织J2EE应用各层的对象。不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的 管理下有机地协调、运行。Spring将各层的对象以松耦合的方式组织在一起,Action对象无须关心Service对象的具体实现,Service对 象无须关心持久层对象的具体实现,各层对象的调用完全面向接口。当系统需要重构时,代码的改写量将大大减少。

    上面所说的一切都得宜于Spring的核心机制,依赖注入。依赖注入让bean与bean之间以配置文件组织在一起,而不是以硬编码的方式耦合在一起

      依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。
      简而言之:所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转;所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中。


    不管是依赖注入,还是控制反转,都说明Spring采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现互相透明。

    关于IOC的学习可以参看帮助文档:spring-3.2.0.M2docs eferencehtml目录下index.html的相关章节

    二、IOC的相关操作
     A、IOC之Bean的实例化方式(只是实例化,并没有初始化)
        1)使用类无参构造器实例化
    <bean id="orderService" class="cn.itcast.OrderServiceBean"/>
        2)使用静态工厂方法实例化
    <bean id="personService" class="cn.itcast.service.OrderFactory" factory-method="createOrder"/>

    public class OrderFactory {
        public static OrderServiceBean createOrder(){
            return new OrderServiceBean();
        }
       3)通过非静态工厂方法实例化:
    <bean id="personServiceFactory" class="cn.itcast.service.OrderFactory"/>
    <bean id="personService" factory-bean="personServiceFactory" factory-method="createOrder"/>

    public class OrderFactory {
        public OrderServiceBean createOrder(){
            return new OrderServiceBean();
        }
    }
    -------------------------------------------------------------

     B、IOC之Bean属性的依赖注入(DI)方式  (即Bean的初始化)

      1)setter方法注入
       Course类中存在如下setter方法:
       public void setId(Intenger id)
       { this.id = id;}
     
       <bean id="course" class="com.etc.vo.Course">
            <property name="id">
                <value>1</value>
            </property>

      </bean>
       2)构造方法注入
       public Course (Interge id , String title,Double price)
       {this.id = id; this.title = title; this.price = price;}
       
       <bean id="course4" class="com.etc.vo.Course">
            <constructor-arg index="0">
                <value>4</value>
            </constructor-arg>
            <constructor-arg index="1">
                <value>Java</value>
            </constructor-arg>
            <constructor-arg index="2">
                <value>1000</value>
            </constructor-arg>
        </bean>

    ###############:上面两种方式也可以写成下面的形式:

       <bean id="orderService" class="cn.itcast.service.OrderServiceBean">
        <constructor-arg index="0" value=“xxx”/>//构造器注入
        <property name=“name” value=“zhao/>//属性setter方法注入

        </bean>

       3)设置注入(使用属性文件的)
        在项目开发中,有时候要从一些配置文件中(properties)读取一些配置信息,如数据库的连接信息。在Spring程序中可以从不同的 properties中读取有用的信息。这里要用到 org.springframeword.beans.factory.config.PropertyPlaceholderConfigurer类,它是BeanFactoryPostProcessor的实现类.

    下面例子:
    项目结构:Spring学习3—控制反转(IOC)Spring依赖注入(DI)和控制反转(IOC)

    connet.properties:

    driver=mysql
    username=yuan
    password=test
    

    test.properties:

    1 age=12
    2 height=13
    3 weight=14
    

    Connect.java装载着两个properties的信息:下面

    public class Connect {
        private String driver;
        private String username;
        private String password;
        int age;
        int height;
        int weight;
            //省略getter,setter   
    }

    beans.xml:

    <?xml version="1.0" encoding="UTF-8"?>
     <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
     
         <bean id="propertyConfigurer"
             class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
             <property name="locations">
                 <list>
                     <value>connect.properties</value>
                     <value>test.properties</value>
                 </list>
             </property>

         </bean>
        
         <bean id="connect" class="com.sunflower.yuan.Connect">
             <property name="driver">
                 <value>${driver}</value>
             </property>
            
             <property name="username">
                 <value>${username}</value>
             </property>
            
             <property name="password">
                 <value>${password}</value>
             </property>
            
             <property name="age">
                 <value>${age}</value>
             </property>
            
             <property name="height">
                 <value>${height}</value>
             </property>
            
            
             <property name="weight">
                 <value>${weight}</value>
             </property>
         </bean>
     
     </beans>

    -------------------------------------------------------------

    C、IOC之针对Bean不同类型属性的不同注入的配置方式(基于B的依赖注入)
     1)属性类型为8中基本数据类型以及其对应的包装类和String
      <bean id="orderService"  class="cn.itcast.service.OrderServiceBean">
        <constructor-arg index="0" value=“xxx”/>//构造器注入
        <property name=“name” value=“zhao/>//属性setter方法注入

       </bean>
     2)属性为其他Bean类型
      public class Order
      {private Int id; private Customer cust;....}
     
     
    <bean id="custom"  class="cn.itcast.service.CustomBean">
        <property name=“name” value="zhao"/>//属性setter方法注入

     </bean>
     
    <bean id="order" class="cn.itcast.service.OrderBean">
    <property name=“id” value=1 />
    <property name=“cust”>
       <ref bean="custom">
     
    </property>
    </bean>

     3)属性为null
      <property name="name">
         <null></null>
      </property>
     或者:
      <property name="name">
         </null>
      </property>
     而不能如下配置(此时该属性不为null,而是空字符串):
      <property name="name">
         <value></value>
      </property>                                   
      4)属性为集合类型    
      public class OrderServiceBean {
        private Set<String> sets = new HashSet<String>();
        private List<String> lists = new ArrayList<String>();
        private Properties properties = new Properties();
        private Map<String, String> maps = new HashMap<String, String>();
            ....//这里省略属性的getter和setter方法
    }
     
    <bean id="order" class="cn.itcast.service.OrderServiceBean">
        <property name="lists">
              <list>
        <value>pkbest</value>
             </list>

          </property>       
          <property name="sets">
             <set>
                <value>pkbest</value>
            </set>

          </property>       
         <property name="maps">
            <map>
                <entry key=“pkbest" value="28"/>
           </map>

         </property>       
         <property name="properties">
            <props>
        <prop key=“pk">best</prop>
           </props>

          </property>
    </bean>


      5)关于使用的注解(Annotation )方式为属性提供的依赖注入,请看下篇博文 -------------------------------------------------------------
    D、Bean的作用域(基于B的依赖注入)

      Bean的作用域共有5种:
       single(单例)
    :默认作用域,只在Spring容器加载时创建唯一的bean实例,因此当多次使用getBean方法返回实例,获得的都是同一个唯一实例。如果想对所有bean都应用延迟初始化,可以在根节点beans设置default-lazy-init=“true“,如下:
     <beans default-lazy-init="true“ ...>
      prototype(原型):每次使用该Bean都会创建新的实例,我们使用spring管理struts2的action时,所有action的Bean的作用域应该是此类型
      request:表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
      session:
    表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
      global session
    .不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。
    以上3种均基于web的Spring ApplicationContext情形下有效

      例如:<bean id=“...” class=“...”  scope=“prototype”/>

    -------------------------------------------------------------
    E、 Bean的初始化方法和销毁方法

       <bean id="xxx" class=“biz.OrderServiceBean" init-method="init" destroy-method="close"/>

      public void init() {
          System.out.println(“已经初始化了”);
      }
      public void close() {
          System.out.println(“被销毁了”);
      }

    总结:IOC和DI的技术基础是基于反射技术和JavaBean的自省技术(自省技术的核心是反射技术)

  • 相关阅读:
    [转]NopCommerce MVC 插件机制分析
    压力测试的轻量级具体做法[转载]
    导入IP安全策略图解
    Grunt使用心得
    解决yarn管理资源管理,其他应用起不来
    Spark 读取mysql中的数据
    Spark 配置连接hive 元数据库(mysql)
    Linux安装anaconda和集成PySpark
    python(配置)
    Python 数据爬取(环境变量)
  • 原文地址:https://www.cnblogs.com/kabi/p/5182026.html
Copyright © 2011-2022 走看看