zoukankan      html  css  js  c++  java
  • 【Spring入门系列】篇3:再探IOC

    前言

    在上一篇SpringIOC入门中我们介绍了SpringIOC的基本使用,现在我们更加深入的学习一下SpringIOC。

    一、Bean的相关配置

    在前文我们简单了解了bean的使用,下面我们再来具体介绍一下bean。

    1.名称与标识

    • id: 使用了约束中的唯一约束。里面不能出现特殊字符的
    • name: 没有使用约束中的唯一约束。里面可以出现特殊字符。

    id我们前文有提到过,就是指定我们需要管理的类方便我们进行获取对象。name作用也是一样,只不过id具有唯一性,name不具有唯一性。我们一般都是使用id不会去使用name。

    2.设置对象的生命周期

    我们还可以通过bean属性来设置对象的生命周期主要有以下两个属性:

    • init-method:Bean被初始化的时候执行的方法
    • destroy-method:Bean被销毁的时候执行的方法(Bean是单例创建,工厂关闭)

    在前文我们说过对象是在ApplicationContext创建时就创建好了,所以init-method会在ApplicationContext创建完就执行,当ApplicationContext工厂关闭时就会执行destroy-method(手动关闭)。接下来我们举个例子:

    首先创建一个Person类,并将Person类交由Spring管理:

    public class Person {
        public void init() {
            System.out.println("person---init");
        }
    
        public void destroy() {
            System.out.println("person---destroy");
        }
    }
    
    <?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">
    
        <bean id="person" class="icu.thinmoon.demo2.Person" init-method="init" destroy-method="destroy"></bean>
    
    </beans>
    

    接着编写测试类运行一下看看结果:

    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class PersonTest {
        @Test
        public void test() {
            ApplicationContext applicationContext
                    = new ClassPathXmlApplicationContext("applicationContext.xml");
            System.out.println("--------------");
        }
    }
    

    运行结果:

    person---init
    --------------
    

    可以看到,在applicationContext初始化完成便调用了person类的init方法。当我们手动关闭工厂的时候,工厂内的所有对象都会被销毁可以看如下代码:

    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class PersonTest {
        @Test
        public void test() {
            ClassPathXmlApplicationContext applicationContext
                    = new ClassPathXmlApplicationContext("applicationContext.xml");
            System.out.println("--------------");
            applicationContext.close();
        }
    }
    

    运行结果:

    person---init
    --------------
    person---destroy
    

    需要注意的是:

    ClassPathXmlApplicationContext applicationContext
                    = new ClassPathXmlApplicationContext("applicationContext.xml");
    

    我们在这使用的是ClassPathXmlApplicationContext 子类,父类接口没有close方法。

    3.Bean的作用范围scope

    我们可以通过配置scope属性来配置bean的作用范围,其具体的值有以下几种:

    意义
    singleton 默认采用此方式,Spring会采用单例模式创建这个对象。工厂关闭自动销毁
    prototype 多例模式。工厂关闭对象不会自动销毁,依旧需要垃圾回收
    request 应用在web项目中,Spring创建这个类以后,将这个对象存入到request范围中。
    session 应用在web项目中,Spring创建这个类以后,将这个对象存入到session范围中
    globalsession 应用在web项目中,必须在porlet(基于Java的Web组件,子域名)环境下使用。但是如果没有这种环境,相对于session。

    我们需要重点关注spring默认是采用单例的方式创建对象,若需改成多例我们需要将scope配置成prototype

    4.工厂实例化的方式

    工厂实例化的方式是指Spring在帮我们生成对象时我们可以指定Spring如何去生成对象,主要有以下三种实现方法:

    • 无参构造:这是默认方法,即Spring调用该类的默认无参构造函数去帮我们创建对象

    • 静态工厂实例化:我们可以利用factory-method属性指定一个静态方法帮助我们生产对象

      public class User {
          public static User create() {
              System.out.println("----create user----");
              return new User();
          }
      }
      
      <bean id="user" class="icu.thinmoon.demo3.User" factory-method="create"></bean>
      
    • 实例工厂实例化:实例工厂实例化是指在利用已有的bean来创建对象

       <bean id="user" class="icu.thinmoon.demo3.User" factory-method="create"></bean>
       <bean id="user2" class="icu.thinmoon.demo3.User" factory-bean="user"></bean>
      

    综上,我们可以通过上述3种方式来设置Spring实例化的方式,在实际使用中一般使用第一种方式比较多。

    二、再探属性注入

    上一篇文章中我们提到了set方法属性注入方式,其实属性注入方式还有很多种我们来挨个学习一下:

    1.set方法属性注入

    前文有提到set方法属性注入,在这我们加上引用类型属性注入方式:

    Student:

    public class Student {
        String name;
        Integer id;
        Dog dog;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    }
    

    Dog:

    public class Dog {
        String name;
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    配置applicationContext.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="dog" class="icu.thinmoon.demo4.Dog">
            <property name="name" value="旺财"/>
        </bean>
    
        <bean id="student" class="icu.thinmoon.demo4.Student">
            <property name="name" value="小明"/>
            <property name="id" value="001"/>
            <property name="dog" ref="dog"/>
        </bean>
    
    </beans>
    

    使用测试类测试一下:

    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class StudentTest {
        @Test
        public void test() {
            ApplicationContext applicationContext
                    = new ClassPathXmlApplicationContext("applicationContext.xml");
            Student student = (Student) applicationContext.getBean("student");
            System.out.println(student.id);
            System.out.println(student.name);
        }
    }
    

    测试结果:

    1
    小明
    

    可以看到,引用类型的属性注入方式与基本类型相似,只不过我们在这使用的是ref属性,表示的是应用工厂内的某个bean,所以我们需要将引用的对象也加入工厂。

     <property name="dog" ref="dog"/>
    

    2.构造方法属性注入

    使用构造方法属性注入肯定需要我们提供构造方法,使用constructor-arg便能完成,修改上面代码如下:

    Student:

    public class Student {
        String name;
        Integer id;
        Dog dog;
    
        public Student(String name, Integer id, Dog dog) {
            this.name = name;
            this.id = id;
            this.dog = dog;
        }
    }
    

    applicationContext.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="dog" class="icu.thinmoon.demo4.Dog">
            <property name="name" value="旺财"/>
        </bean>
    
        <bean id="student" class="icu.thinmoon.demo4.Student">
            <constructor-arg name="name" value="小明"/>
            <constructor-arg name="id" value="001"/>
            <constructor-arg name="dog" ref="dog"/>
        </bean>
    
    </beans>
    

    测试类及测试结果同上。

    3.p名称空间属性注入

    p名称空间属性注入其实就是set方法属性注入的一种简化写法,使用p名称空间属性注入我们首先要在配置文件中加上下面这条代码:

    xmlns:p="http://www.springframework.org/schema/p"
    

    使用p名称空间后的配置文件如下:

    <?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.xsd">
    
        <bean id="dog" class="icu.thinmoon.demo4.Dog" p:name="旺财"/>
    
        <bean id="student" class="icu.thinmoon.demo4.Student" p:name="小明" p:id="001" p:dog-ref="dog"/>
            
    
    </beans>
    

    以上配置文件和set属性注入执行效果完全一致。

    4.spEL表达式属性注入

    spEL表达式也是一种简写方式,我们可以通过spEL表达式直接引用对象甚至对象的属性,比如说:

    <?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.xsd">
    
        <bean id="dog" class="icu.thinmoon.demo4.Dog">
            <property name="name" value="旺财"/>
        </bean>
    
        <bean id="student" class="icu.thinmoon.demo4.Student">
            <property name="name" value="#{‘小明’}"/>
            <property name="id" value="#{1}"/>
            <property name="dog" value="#{dog}"/>
        </bean>
    
    </beans>
    

    我们可以通过#{}的形式进行注入,字符串需要加上单引号。我们还可以在括号内调用对象属性、方法等,类似这样:

    <property name="name" value="#{dog.name}"/>
    

    这种方式开发过程一般不使用,了解即可。

    5.集合属性注入

    修改Student如下:

    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    public class Student {
    
        String[] array;
        List<String> list;
        Set<String> set;
        Map<Integer, String> map;
    
        public void setArray(String[] array) {
            this.array = array;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        public void setSet(Set<String> set) {
            this.set = set;
        }
    
        public void setMap(Map<Integer, String> map) {
            this.map = map;
        }
    }
    
    

    applicationContext.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.xsd">
    
        <bean name="student" class="icu.thinmoon.demo4.Student">
            <!--数组注入-->
            <property name="array">
                <list>
                    <value>小明</value>
                    <value>小红</value>
                    <value>小红</value>
                    <value>小红</value>
                </list>
            </property>
    
            <!--List注入-->
            <property name="list">
                <list>
                    <value>小明</value>
                    <value>小红</value>
                    <value>小红</value>
                    <value>小红</value>
                </list>
            </property>
    
            <!--set注入-->
            <property name="set">
                <set>
                    <value>小明</value>
                    <value>小红</value>
                    <value>小红</value>
                    <value>小红</value>
                </set>
            </property>
    
            <!--map-->
            <property name="map">
                <map>
                    <entry key="001" value="abc"/>
                    <entry key="002" value="def"/>
                    <entry key="003" value="ghj"/>
                </map>
            </property>
    
    
        </bean>
    
    </beans>
    

    附录:分模块配置

    我们在开发中每个人都可以写一个自己的配置文件,然后在主配置文件中进行引入即可:

    applicationContext.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--id: 为自己取得名称  class:具体实现类的全路径-->
        <bean id="userDao" class="icu.thinmoon.demo1.UserDaoMysqlImpl">
            <!--
            name: 属性名称
            value: 属性的值
            注意:需要提供set方法
            -->
            <property name="name" value="thinmoon"/>
        </bean>
    
        <!--导入另外的配置文件-->
        <import resource="applicationContext2.xml"/>
    
    </beans>
    
    

    applicationContext2.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="user" class="icu.thinmoon.demo3.User" factory-method="create"></bean>
        <bean id="user2" class="icu.thinmoon.demo3.User" factory-bean="user"></bean>
    
    </beans>
    
  • 相关阅读:
    Codefroces 920F SUM and REPLACE(线段树)
    POJ 2155 Matrix (2维树状数组)
    POJ 3067 Japan (树状数组求逆序对)
    Codeforces 919D Substring (拓扑排序+树形dp)
    拓扑排序
    Codeforces 889F Letters Removing(二分 + 线段树 || 树状数组)
    线段树扫描线(2---算矩形的相交面积)
    线段树扫描线(1---算矩形的总面积)
    hdu 6168 Numbers
    Educational Codeforces Round 27 A B C
  • 原文地址:https://www.cnblogs.com/ThinMoon/p/13206851.html
Copyright © 2011-2022 走看看