美文网首页
Spring配置——IoC容器装配Bean_基于XML配置方式

Spring配置——IoC容器装配Bean_基于XML配置方式

作者: 花无缺_0159 | 来源:发表于2019-02-05 10:53 被阅读0次

    【目录】
    3.1 XML文件最基本的元素:Bean元素
      3.1.1 Bean元素基本属性
      3.1.2 Bean标签创建方式
      3.1.3 Bean的生命周期
    3.2 Bean元素的注入方式
      3.2.1 set方法属性注入
      3.2.2 构造器参数注入
      3.2.3 注入复杂类型

    3.1 XML文件最基本的元素:Bean元素

    Bean元素:交由Spring管理的对象都要配置在bean标签中。
    <bean>:原意是“豆子”,在Spring中,可以认为一个bean就是一个对象。

    3.1.1 Bean元素基本属性

    示例代码:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:p="http://www.springframework.org/schema/p"
           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元素 -->
        <bean id="hello" name="hello1,hello2" class="com.test.HelloWorld" scope="prototype">
    <!-- 属性配置 -->
              <property name="name" value="hhhhh" />
        </bean>
        
    </beans>
    

    具体说明:

    1. id:bean的名称(对象的名称),在应用程序中,可以根据id值得到配置对象。id的名字必须满足XML的命名规范,不能包含特殊字符或中文,习惯上会使用接口的名字小写。注意:id名在整个Spring的配置文件中,必须唯一。
    2. name:为id创建一个或多个别名,可以包含特殊符号。

    注意:id和name都可以指定多个名字,名字之间可用逗号、分号、或者空格间隔。

    1. class:是实现类的全名(填写创建对象所在类的全路径),Spring工厂会自动根据该类型名字,采用反射机制来得到具体的类的类型。
    2. scope:bean的作用范围。有以下5个常用属性值:
      (1)singleton:默认值,表示整个IOC容器共享一个Bean,也就是说每次说每次通过getBean获取的bean都是同一个。
      (2)prototype:每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。
      (3)request:在web项目中,创建对象并把对象放到request域里面,每次HTTP请求将会生成各自的bean实例。
      (4)session :在web项目中,创建对象并把对象放到到session域中,每次会话请求对应一个bean实例。
      (5)globalSession:在web项目中,应用在prolet环境,如果没有prolet环境那么globalSession相当于session。一般用于全局session共享账号。
    图示

    补充:延迟加载

    3.1.2 Bean标签创建方式

    1. 空参构造:最常用的创建方式。
      过程很简单,就是在类中创建一个无参数的构造方法。
      例如:
    public class User {
      public User() {
     }
    }
    

    一般来说,如果不写无参数的参构造方法,也没有关系,因为在类中会默认有一个隐藏的无参构造方法(不显示在代码中)。
    但是注意! 如果你在类中定义了带参的构造方法,那么这个类默认的无参的构造方法没有了,需要手动加上去才行。——这牵涉到我们后面的一个知识点:如果采用构造方法的注入方式(后面讲解三种注入方式),就必须把无参数的参构造方法写出来。不然就会报错误:No default constructor found......
    所以这里推荐在编写代码时,把无参数的参构造方法都写出来。

    1. 静态工厂
    2. 实例工厂

    静态工厂和实例工厂的更多内容推荐看这里Spring创建Bean的三种方式的使用和区别

    1. FactoryBean方式:源码底层用的多。不作详细介绍了。只需要区别好BeanFactory和FactoryBean:
      BeanFactory:是一个工厂(其实是构建了一个spring上下文的环境,容器),用来管理和获取很多Bean对象,
      FactoryBean:是一个Bean生成工具,是用来获取一种类型对象的Bean,它是构造Bean实例的一种方式。

    总结:以上四种,第一种最常用,第二、三、一些框架初始化的时候用的多、第四种spring底层用的多。

    3.1.3 Bean的生命周期

    通过 init-method属性 指定初始化的方法。
    通过 destroy-method属性 指定销毁对象的方法 。

    3.2 Bean元素的注入方式

    Bean元素的注入有三种方法,分别是set方法属性注入、构造器参数注入、接口注入 。
    (Spring 框架规范中通过配置文件配置的方式,只支持set方法属性注入和构造器参数注入,不支持接口注入,所以这里只讲解前两种注入方式。)
    注入类型有值类型(八大基本数据类型)、引用类型(String、自定义对象等)和复杂类型(Array、List、Set、Map、Properties)。

    3.2.1 set方法属性注入

    在类中加set方法,然后在配置文件中用<property>标签注入bean即可。
    (用此方法展示注入值类型和引用类型,后续方法中不再演示。注入复杂类型在3.2.3单独介绍。)
    下面开始演示。

    1.注入值类型。代码如下。
    实体类User.java:

    package user;
    
    public class User {
        private Integer u_id;
        private String u_username;
        private String u_password;
        
         //这里是空参构造
        public User() {
        }
        
        public Integer getU_id() {
            return u_id;
        }
        public void setU_id(Integer u_id) {
            this.u_id = u_id;
        }
        public String getU_username() {
            return u_username;
        }
        public void setU_username(String u_username) {
            this.u_username = u_username;
        }
        public String getU_password() {
            return u_password;
        }
        public void setU_password(String u_password) {
            this.u_password = u_password;
        }
        
        @Override
        public String toString() {
            return "User [u_id=" + u_id + ", u_username=" + u_username + ", u_password=" + u_password 
                    + "]";
        
        }
    }
    

    配置文件applicationContext_Injection.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 将user对象交给spring管理,并用value注入值类型 -->
    <bean name="user" class="user.User">
        <property name="u_id" value="1"/>
        <property name="u_username" value="set注入-值类型"/>
        <property name="u_password" value="123"/>
    </bean>
    
    </beans>
    

    测试类 Test_Injection.java:

    package user;
    
    import org.junit.Test;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test_Injection {
        @Test
        public void Test() {
            ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_Injection.xml");
            User u1 = (User) ac.getBean("user");
            System.out.println(u1); 
            //关闭容器
            ac.close();
        }
    }
    

    进行测试。

    测试结果

    2.注入引用类型。
    在刚刚的工程中新建一个Pet.java,代码如下。

    Pet.java:

    package user;
    
    public class Pet {
        //宠物类型 猫 狗
        private String petType;
        //宠物的颜色
        private String color;
        
        public String getPetType() {
            return petType;
        }
        
        public void setPetType(String petType) {
            this.petType = petType;
        }
        
        public String getColor() {
            return color;
        }
        
        public void setColor(String color) {
            this.color = color;
        }
        @Override
        public String toString() {
            return "Pet [petType=" + petType + ", color=" + color + "]";
        }
        
    }
    

    在User.java里加入宠物字段。
    User.java:

    package user;
    
    public class User {
        private Integer u_id;
        private String u_username;
        private String u_password;
         
        //这里是空参构造
        public User() {
        }
    
        private Pet u_pet;
    
        public Pet getU_pet() {
            return u_pet;
        }
    
        public void setU_pet(Pet u_pet) {
            this.u_pet = u_pet;
        }
    
        public Integer getU_id() {
            return u_id;
        }
    
        public void setU_id(Integer u_id) {
            this.u_id = u_id;
        }
    
        public String getU_username() {
            return u_username;
        }
    
        public void setU_username(String u_username) {
            this.u_username = u_username;
        }
    
        public String getU_password() {
            return u_password;
        }
    
        public void setU_password(String u_password) {
            this.u_password = u_password;
        }
    
        @Override
        public String toString() {
            return "User [u_id=" + u_id + ", u_username=" + u_username + ", u_password=" + u_password + ", u_pet=" + u_pet
                    + "]";
        }
    }
    

    修改配置文件。
    applicationContext_Injection.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 将pet对象-dog交给spring管理,并用value注入值类型 -->
    <bean name="dog" class="user.Pet">
        <property name="PetType" value="二哈"/>
        <property name="color" value="灰灰的"/>
    </bean>
    
    <!-- 将user对象交给spring管理 -->
    <bean name="user" class="user.User">
        <!-- 注入值类型 -->
        <property name="u_id" value="1"/>
        <property name="u_username" value="set注入-引用类型"/>
        <property name="u_password" value="123"/>
        <!-- 用ref注入引用类型 -->
        <property name="u_pet" ref="dog"/>
    </bean>
    
    </beans>
    

    进行测试。

    测试结果

    3.2.2 构造器参数注入

    首先在类中编写一个带参数的构造方法,然后在配置文件中用<constructor-arg>标签注入bean即可。
    下面开始演示。

    在刚刚的工程中修改User.java,添加一个带参数(String u_username, Pet u_pet)的构造方法。
    User.java:

    package user;
    
    public class User {
       private Integer u_id;
       private String u_username;
       private String u_password;
    
       //这里是空参构造
       public User() {
       }
       //带参数的构造方法   
       public User(String u_username, Pet u_pet) {
           this.u_username = u_username;
           this.u_pet = u_pet;
       }
       
       private Pet u_pet;
    
       public Pet getU_pet() {
           return u_pet;
       }
    
       public void setU_pet(Pet u_pet) {
           this.u_pet = u_pet;
       }
    
       public Integer getU_id() {
           return u_id;
       }
    
       public void setU_id(Integer u_id) {
           this.u_id = u_id;
       }
    
       public String getU_username() {
           return u_username;
       }
    
       public void setU_username(String u_username) {
           this.u_username = u_username;
       }
    
       public String getU_password() {
           return u_password;
       }
    
       public void setU_password(String u_password) {
           this.u_password = u_password;
       }
    
       @Override
       public String toString() {
           return "User [u_id=" + u_id + ", u_username=" + u_username + ", u_password=" + u_password + ", u_pet=" + u_pet
                   + "]";
       }
    }
    

    修改配置文件。
    applicationContext_Injection.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 将pet对象-dog交给spring管理,并用value注入值类型 -->
    <bean name="dog" class="user.Pet">
        <property name="PetType" value="二哈"/>
        <property name="color" value="灰灰的"/>
    </bean>
    
    <!-- 将user对象交给spring管理 -->
    <bean name="user" class="user.User">
        <property name="u_id" value="1"/>
        <property name="u_username" value="set注入-引用类型"/>
        <property name="u_password" value="123"/>
        <!-- 用ref注入引用类型 -->
        <property name="u_pet" ref="dog"/>
    </bean>
    
    
    <!--构造器参数注入 -->
    <bean name="user1" class="user.User">
        <constructor-arg name="u_username" value="构造器参数注入" />
        <constructor-arg name="u_pet" ref="dog"/>
    </bean>
    </beans>
    

    修改测试类。
    Test_Injection.java:

    package user;
    
    import org.junit.Test;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Test_Injection {
        @Test
        public void Test() {
            ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_Injection.xml"); 
            User u1 = (User) ac.getBean("user1");
            System.out.println(u1);     
            //关闭容器
            ac.close();
        }
    }
    

    进行测试。

    测试结果

    补充:
    我们知道,在一个类里,可以进行方法的重载( 重载与重写的区别),构造方法可以有多个。我们怎么让bean精准定位到某一个构造方法呢?这就要用到<constructor-arg>标签的type和index属性了。

    • 构造方法参数不同时,用type指定一个不同参数的类型,就可以定位构造方法。
      ( 有多个构造方法,却不使用type,那么就会自动定位到第一个构造方法。)
    • 构造方法参数相同,位置不同时,用type和index可以共同指定某个参数的位置(从构造函数第一个参数开始index+,第一个参数的index=0),从而定位构造方法。
      (只使用type或index的其中一个——只用type,会定位到更新的那一个构造方法;而index无法单独使用。)

    【演示】
    修改User.java,添加一个与方法1参数不同的方法2。代码片段如下:

       //不同参数的构造
       //方法1   
        public User(String u_username, Pet u_pet) {
            System.out.println("方法1 String, Pet");
            this.u_username = u_username;
            this.u_pet = u_pet;
        }
        //方法2 
        public User(Integer u_username, Pet u_pet) {
            System.out.println("方法2 Integer, Pet");
            this.u_username = u_username.toString();
            this.u_pet = u_pet;
        }
    

    修改配置文件片段,指定type=Integer。同时,把value改成66,因为要传一个Integer类型的值。

    <bean name="user1" class="user.User">
        <constructor-arg name="u_username" value="66" type="java.lang.Integer" />
        <constructor-arg name="u_pet" ref="dog"/>
    </bean>
    
    运行结果

    修改User.java,添加一个与方法2参数相同,位置不同的方法3。代码片段如下:

       //方法1   
        public User(String u_username, Pet u_pet) {
            System.out.println("方法1 String, Pet");
            this.u_username = u_username;
            this.u_pet = u_pet;
        }
        //方法2 
        public User(Integer u_username, Pet u_pet) {
            System.out.println("方法2 Integer, Pet");
            this.u_username = u_username.toString();
            this.u_pet = u_pet;
        }
        //方法3 
        public User(Pet u_pet, Integer u_username) {
            System.out.println("方法3 Pet, Integer ");
            this.u_username = u_username.toString();
            this.u_pet = u_pet;
        }
    

    不修改配置文件,仍然只指定type=Integer,可以看到运行结果,定位到方法3而非方法2。

    定位到更新的方法3而非方法2

    配置文件片段,指定type=Integer和index=0。

    <bean name="user1" class="user.User">
        <constructor-arg name="u_username" value="66" type="java.lang.Integer" index="0" />
        <constructor-arg name="u_pet" ref="dog"/>
    </bean>
    

    运行。

    指定到方法2

    3.2.3 注入复杂类型

    注入复杂类型也就是注入集合类型 (Array、List、Set、Map、Properties),属于了解内容,在使用时查看即可。
    作用:主要用于框架整合配置。
    Spring为集合提供了对应的标签:
    <array>注入 array元素
    <list> 注入 list元素
    <set> 注入 set元素
    <map> 注入 map元素
    <props> 注入 properties 元素 (hashtable类的子类,是特殊的map,key和value都是String )

    下面给出参考代码。
    集合类代码如下:

    package com.sikiedu.bean;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    import java.util.Set;
    
    public class MyCollection {
        //数组
        private Object[] array;
        //list
        private List list;
        //set
        private Set set;
        //map
        private Map map;
        //properties
        private Properties prop;
        public Object[] getArray() {
            return array;
        }
        public void setArray(Object[] array) {
            this.array = array;
        }
        public List getList() {
            return list;
        }
        public void setList(List list) {
            this.list = list;
        }
        public Set getSet() {
            return set;
        }
        public void setSet(Set set) {
            this.set = set;
        }
        public Map getMap() {
            return map;
        }
        public void setMap(Map map) {
            this.map = map;
        }
        public Properties getProp() {
            return prop;
        }
        public void setProp(Properties prop) {
            this.prop = prop;
        }
        @Override
        public String toString() {
            return "MyCollection [list="+list+",set="+set+",map=" + map + ", prop=" + prop + "]";
        }   
    }
    

    xml代码片段如下:

    <!-- 复杂类型注入 -->
    <bean name="collection" class="com.sikiedu.bean.MyCollection">
        <!-- array -->
        <!-- 一个数据可以这样写 -->
          <property name="array" value="123">
        <!--多个数据可以这样写 
          <property name="array">
            <array>
                <value>123</value>
                <value>abc</value>
                <ref bean="dog"/>
            </array> -->
        </property>
        
        <!-- list -->
        <property name="list">
            <list>
                <value>456</value>
                <value>cba</value>
                <ref bean="user1"/>
            </list>
        </property>
        
        <!--set -->
        <property name="set">
            <set>
                <value>111</value>
                <value>aaa</value>
                <ref bean="user1"/>
            </set>
        </property>
        
        <!-- map -->
        <property name="map">
            <map>
                <entry key="username" value="root"/>
                <entry key="password" value="123"/>
                <entry key-ref="user1" value-ref="dog"/>
            </map>
        </property>
        
        <!-- properties -->
        <property name="prop">
            <props>
                <prop key="name">老李</prop>
                <prop key="age">25</prop>
            </props>
        </property>
        
    </bean>
    

    相关文章

      网友评论

          本文标题:Spring配置——IoC容器装配Bean_基于XML配置方式

          本文链接:https://www.haomeiwen.com/subject/xkxvsqtx.html