• (二)Spring中的ioc


    目录


    Springioc操作

    1. 把对象的创建交给Spring管理
    2. ioc操作分为两种
      • 配置文件方式
      • 注解方式

    ioc底层使用的技术

    1. xml配置文件
    2. dom4j解析xml文件、
    3. 工厂设计模式
    4. 反射

    ioc底层原理

    需求:创建一个类,并其调用其非静态方法;、

    • 没有使用Spring之前
    • IOC过程一

    我们知道不能在servlet中,直接new services层对象,导致 web 层和 services 层的耦合太高;没接触Spring之前,我们一般使用工厂来解耦web 层和 services 层 ;

    但是这样做,又导致services 层和 工厂 紧紧的关联在一起,它们的耦合又变得太高了!比如,现在services层,有类的名字发生了改变,那么工厂类中,也需要相应的改变类的名字;因此本质上,并没有解决耦合的问题;

    • 使用Spring之后
      这里写图片描述

    假如我们在,配置文件中,配置要创建对象的类,然后创建一个工厂类,在工厂类中,使用dom4j解析xml配置文件,然后利用反射,创建对象;

    这样,后期即使要改动,比如改动了类的名字,我们也只需要在配置文件改动类的名字,其他地方的代码是不需要改变的

    Springioc,就是这样帮我们创建对象的;上面也就是IOC的底层原理;


    ioc入门案例

    1. 导入Spring jar

      spring最基本的功能时,只需要导入四个核心jar包:BeansCoreContextSpEL 即可;

    2. 导入支持日志的 jar

          因为,Spring本身没有支持日志;
      

      日志 jarlog4jcommons-logging

    3. spring 配置文件

      (1) 配置文件的名字和位置,不是固定的,可以随便放置;官方建议放在 src 目录下,取名为 ApplicationContext.xml

      (2) 引入 schema 约束文件

      <?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 "
         default-autowire="byName">
      
      <bean id="user" class="xin.ijava.domian.User"/>
      </beans>
      
    4. 代码实例

       @Test
      public void testIoc(){
      //        1、加载Spring配置文件,参数配置文件的路径+名字;从src开始写
          ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
      //        2、获取配置文件中配置的对象
          User user = (User) context.getBean("user");
          System.out.println(user);
          user.speak();
      }
      
      -------------------  输出  -------------------------------
      
      xin.ijava.domian.User@6c1ec7a3
      User 说话、、
      
      

    bean管理(xml方式)

    也就是 ioc 操作
    
    1. bean实例化(三种方式实现)

      实例化,就是通过配置文件由 Spring 来创建对象;
      
      基本上只用第一种方式创建对象;
      

      第一种:使用类的无参构造器创建(重点

      只需要写出一个 bean 类即可;

      配置文件中写法

      <!--无参构造器创建bean实例-->
      <bean id="user" class="xin.ijava.domian.User"/>



      第二种:使用静态工厂创建没有创建工厂对象

      除了 bean 类,还需要写一个bean的工厂,工厂中含有静态方法,返回bean

      配置文件中写法:

      class属性为:工厂类factory-method属性为:工厂静态方法

       <!--静态工厂方法创建bean实例-->
       <bean id="bean2" class="xin.ijava.domian.Bean2Factory" factory-method="getBean2"/>



      第三种:使用实例工厂创建创建工厂了对象

      配置文件中写法:先创建工厂实例,再利用工厂实例创建bean实例

      <!--实例工厂方法创建bean实例-->
      <bean id="bean3Factory" class="xin.ijava.domian.Bean3Factory"/>
      <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"/>

    2. bean标签常用属性

      id:

      起名字,名字可以为任意名字,但是名字中不可以有特殊字符;
      
      可以根据 id,获取配置对象;
      

      class:

      创建对象所在类的全路径;
      

      name:

      功能和 id  一样,但是可以包含特殊字符,主要是为了整合 Struts1 的遗留问题
      
      现在也不再使用,推荐使用 id ;
      

      scope:

      Bean 的作用范围 ;有几个可选值  ;
      
      singleton :默认值,单例
      prototype :多例
      
      request:Spring创建的对象,保存在request域中 ;
      session:Spring创建的对象,保存在session域中 ;  
      globalSession:应用在 Porlet 环境,如果没有 Porlet 环境,则globalSession相当于 session ;
      
      最后的 globalSession ,用于单点登录的时候;
      

    3. 属性注入

      属性注入:创建对象的时候,往类里面属性设置值;
      
      属性注入有三种方式;
      

      第一种:使用 set 方法注入(重点

      使用这样方式,类中必须要有无参构造器,因为底层实现的时候,也是先创建对象,再赋值属性的;

      配置文件写法:

      <!--set 方法注入,需要有无参的构造器存在,因为是先new对象出来,再复制的-->
      <bean id="book2" class="xin.ijava.domian.Book" >
          <property name="name" value="哆啦A梦"></property>
      </bean>



      第二种:使用 有参构造器 方法注入

      这样注入,不需要有无参构造器存在,因为底层实现的时候,是直接调用有参构造器;

      配置文件写法:

      <!--属性注入。使用有参构造器-->
      <bean id="book1" class="xin.ijava.domian.Book" >
          <constructor-arg name="name" value="肥嘟嘟左卫门"></constructor-arg>
      </bean>

    4. 注入对象类型属性

      使用场景:在 Services 层调用 Dao 层方法,我们将dao的创建工作交给 Spring
      
      /**
      * Dao层代码
      */
      package xin.ijava.domian;
      
      public class UserDao {
          public void add(){
              System.out.println("UserDao ...  add");
          }
      }
      
      -------------------------------------------
      
      package xin.ijava.domian;
      /**
      * Service层代码
      */
      public class Service {
          // 将dao层作为属性
          private UserDao userDao ;
      
          public UserDao getUserDao() {
              return userDao;
          }
          // 设置set 方法,便于 set 注入
          public void setUserDao(UserDao userDao) {
              this.userDao = userDao;
          }
      
          public void add(){
              System.out.println("Service ... add");
              userDao.add();
          }
      
      }

      配置文件写法:

       <!--对象属性注入-->
      <!--创建dao层对象-->
      <bean id="userDao" class="xin.ijava.domian.UserDao"></bean>
      <!--创建services层对象,将dao层对象注入进去-->
      <bean class="xin.ijava.domian.Service" id="service">
          <!--对于引用类型,使用 ref ,不可使用value-->
          <property name="userDao" ref="userDao"></property>
      </bean>
      

    5. P名称空间注入

      <beans xmlns="http://www.springframework.org/schema/beans"
      <!--自定义名称空间P-->
         xmlns:p="http://www.springframework.org/schema/p"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      
       <!--P名称空间注入-->
      <bean id="book3" class="xin.ijava.domian.Book" p:name="啦啦啦"/>
    6. 复杂类型属性注入

      涉及数组maplistproperties 等类型 ;

       <!--复杂类型属性注入-->
      <bean class="xin.ijava.domian.Bean4" id="bean4">
      
          <!--为数组赋值。使用list,就是list一脉下面的集合,就是有list赋值-->
          <!--list下面使用value-->
          <property name="strings">
              <list>
                  <value>那么多唱歌动听的人呦。。。</value>
                  <value>千秋直美</value>
                  <value>村下孝藏</value>
                  <value>那么多唱歌动听的人呦。。。</value>
              </list>
          </property>
      
          <!--为list集合赋值-->
          <property name="list">
              <list>
                  <value>哈哈</value>
                  <value>呵呵</value>
              </list>
      
          </property>
      
          <!--为map赋值-->
          <!--使用键值对一脉的,都是用map赋值-->
          <!--而map使用 entry-->
          <property name="map">
              <map>
                  <entry key="driverClass" value="com.mysql.jdbc.driver"></entry>
              </map>
          </property>
      
          <!--为properties赋值-->
          <!--使用props赋值-->
          <property name="properties">
              <props>
                  <prop key="name" >root</prop>
                  <prop key="password" >root</prop>
              </props>
          </property>
      </bean>

    IOCDI的区别

    IOC:控制反转,是将对象的创建交给 Spring 来完成 ;
    DI :依赖注入,是为对象的属性赋值 ;

    关系DI 不能单独存在,必须依赖于 IOC


    Spring整合WEB的原理

    1. 加载 Spring 的核心配置文件

      //        1、加载Spring配置文件,参数配置文件的路径+名字;从src开始写
          ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
      
    2. new 对象的效率问题

      假如每个地方需要用到配置文件的话,都new 一个对象的话,那么效率会低到爆炸;

      你可能会想到在 静态代码块 里面new,然后复用它,这样第一次使用的时候,还是需要等待的;

    3. 在服务器启动的时候,创建配置文件对象

      将压力扔给服务器,在服务器启动的时候,让服务器创建配置文件对象,这样第一次用的时候,对象就已经被创建好了;

    4. 共享配置文件对象

      服务器在启动的时候,会为每一个项目,创建一个servletContext 对象,使用监听器,监听 servletContext 对象的创建 ,就监听到服务器的启动,在监听器里面创建配置文件对象,然后将其添加进 servletContext 域中,就可以共享配置文件对象了 ;

      上面说的,也就是 Spring 自动创建配置对象的原理


    Spring 整合的具体操作

    1. Spring 中具体操作步骤

      上面说到,我们可以通过 监听器servletContext 实现在服务器启动的时候,加载配置文件,创建配置文件对象 ;

      但是在 Spring 中,不需要我们自己动手写上面的代码。Spring对其做了封装 ;

      Spring 自己封装了一个监听器,我们那只需要去配置这个监听器即可,配置之前,确保导入了 Spring-web 的包 ;

      <!--配置Spring的监听器-->
      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>

      加上监听器以后,这时候会报错:

      Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml]

      告诉我们,在 WEB-INF 目录下,找不到名字叫 applicationContext.xml 的配置文件 ;

      这时候,我们可以将配置文件放在对应的目录下面,起对应的名字 ;

      但是,我们刚学 Spring 的时候,就被告知配置文件是可以随便放在哪里的,名字随便起的 ;这时候,需要我们在 Web.xml 中再配置一下:

      
      <!--配置Spring的配置文件路径-->
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:ApplicationContext.xml</param-value>
      </context-param>

      其中:<param-name> 属性的值是固定的 ;<param-value> 属性的值是 classpath: 后面跟上 Spring 配置文件的位置和名字 ;

      然后运行项目,在控制台可以看到:

      INFO XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [ApplicationContext.xml]

      可以看到,我们的 Spring 配置文件被加载了 ;

  • 相关阅读:
    linux
    网络编址
    抽象类 接口
    mysql
    java
    [lyu]Mysql解压版安装教程
    Mysql出现拒绝本地账户访问的情况副本
    js
    Redis限流和GeoHash
    布隆过滤器
  • 原文地址:https://www.cnblogs.com/young-youth/p/11665690.html
Copyright © 2020-2023  润新知