美文网首页
Spring学习笔记 | 详解bean的配置(一)

Spring学习笔记 | 详解bean的配置(一)

作者: 一颗白菜_ | 来源:发表于2019-10-08 20:47 被阅读0次

    IOC和DI概述

    IOC其思想是反转资源获取的方向,传统的资源查找方式要求组件向容器发起请求查找资源。作为回应,容器适时的返回资源,而应用了IOC之后,则是容器主动地将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源,这种行为也被称为查找的被动形式。

    DI是IOC的另一种表述方式,即**组件以一些预先定义好的方式(例如setter())接受来自容器的资源注入,相对于IOC而言,这种表述更直接。


    配置Bean

    在ApplicationContext.xml中配置bean

    <?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-->
        <bean id="helloWorld" class="com.spring.helloworld.HelloWorld">
            <!-- name为属性名-->
            <property name="name" value="Spring"></property>
        </bean>
    </beans>
    

    class:bean的全类名,通过反射的方式在IOC容器中创建bean,所以要求bean中必须有无参数的构造器。
    id:标识容器中的bean,id唯一。


    Spring容器

    在SpringIOC容器读取bean配置创建bean实例之前,必须对它进行实例化,只有在容器实例化后,才可以从IOC容器里获取bean实例并使用。

    Spring提供了两种类型的IOC容器实现

    • BeanFactory:IOC容器的基本实现
    • ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口。
      ClassPathXmlApplicationContextApplicationContext的一个实现类,其作用是从类路径下加载配置文件。

    BeanFactory是Spring框架的基础实施,面向Spring本身;ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory。但是无论使用何种方式,其配置文件都是相同的。


    依赖注入

    Spring支持3种依赖注入的方式

    • 属性注入
    • 构造器注入
    • 工厂方法注入(很少使用)

    属性注入

    属性注入即通过setter()注入Bean的属性值或依赖的对象

    属性注入使用<property>元素,使用name属性指定Bean的属性名称,value属性或<value>子节点指定属性值。属性注入是实际应用中最常用的注入方式

    <bean id="helloWorld" class="com.spring.helloworld.HelloWorld">
            <!-- name为属性名-->
            <property name="name" value="Spring"></property>
    </bean>
    

    构造方法注入

    通过构造方法注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后就可以使用。
    构造器注入在<constructor-arg>元素里声明属性,<constructor-arg>中没有name属性

    首先要有相应的构造器:

    package com.spring.helloworld;
    
    public class Car {
        private String brand;
        private String corp;
        private int price;
        private int maxSpeed;
    
        public Car(String brand, String corp, int price) {
            this.brand = brand;
            this.corp = corp;
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Car{" +
                    "brand='" + brand + '\'' +
                    ", corp='" + corp + '\'' +
                    ", price=" + price +
                    ", maxSpeed=" + maxSpeed +
                    '}';
        }
    }
    

    在ApplicationContext.xml文件中的构造方法注入:

    <!-- 通过构造器注入属性值可以指定参数的位置和参数的类型,以区分重载的构造器 -->
        <bean id="car2" class="com.spring.helloworld.Car">
            <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
            <constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
            <constructor-arg value="300000" type="int"></constructor-arg>
        </bean>
    

    Spring属性配置细节

    字面值

    可用字符串表示的值,可用通过<value>元素标签或value属性进行注入。

    基本数据类型及其封装类、String等类型都可以采取字面值注入的方式。若字面值中包含特殊字符,可用使用<![CDATA[]]>把字面值包裹起来。

    <bean id="car" class="com.spring.helloworld.Car">
            <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
            <constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
            <constructor-arg value="300000" type="int"></constructor-arg>
        </bean>
    

    引用其它Bean

    组成应用程序的Bean经常需要相互协作以完成引用程序的功能,要使Bean能够相互访问,就必须在Bean配置文件中指定对Bean的引用。

    在Bean的配置文件中,可以通过<ref>元素或ref属性来为Bean的属性或构造器参数指定对Bean的引用。

    也可以在属性或构造器里包含Bean的声明,这样的Bean称为内部Bean

    我们先建立一个Person类,如下:

    package com.spring.helloworld;
    
    public class Person {
        private String name;
        private int age;
        private Car car;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Car getCar() {
            return car;
        }
    
        public void setCar(Car car) {
            this.car = car;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", car=" + car +
                    '}';
        }
    }
    
    

    在ApplicationContxt.xml文件中配置如下:

    <bean id="person" class="com.spring.helloworld.Person">
            <property name="name" value="Tom"></property>
            <property name="age" value="24"></property>
            <!-- 使用ref来建立bean之间的引用关系-->
            <property name="car" ref="car2"></property>
        </bean>
    

    测试类:

    package com.spring.helloworld;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
        public static void main(String[] args) { 
            Person person = (Person) context.getBean("person");
            System.out.println(person);
        }
    }
    

    内部Bean

    当Bean实例仅仅给一个特定的属性使用时,可以将其声明为内部Bean,内部Bean声明直接包含在<property><constructor-arg>元素里,不需要设置任何idname属性。

    内部Bean不能使用在任何其他地方。

    内部类的一个注入实例:

    <bean id="person" class="com.spring.helloworld.Person">
            <property name="name" value="Tom"></property>
            <property name="age" value="24"></property>
            <!-- 内部bean-->
            <property name="car">
                <bean id="car3" class="com.spring.helloworld.Car">
                    <!-- 下面是使用构造方法注入,也可以使用属性注入的方式 -->
                    <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
                    <constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
                    <constructor-arg value="300000111" type="int"></constructor-arg>
                </bean>
            </property>
    </bean>
    

    注入参数详解:null值和级联属性

    可以使用专用的<null/>元素标签为Bean的字符串或其他对象类型的属性注入null值。

    和Struts、Hibernate等框架一样,Spring支持级联属性的配置。

    <?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="car2" class="com.spring.helloworld.Car">
            <constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
            <constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
            <constructor-arg value="300000" type="int"></constructor-arg>
        </bean>
    
        <bean id="person" class="com.spring.helloworld.Person">
            <property name="name" value="Tom"></property>
            <property name="age" value="24"></property>
            <!-- 使用ref来建立bean之间的引用关系-->
            <property name="car" ref="car2"></property>
            <!-- 为级联属性赋值. 注意:属性需要先初始化后才可以为级联属性赋值,否则会有异常 -->
            <property name="car.maxSpeed" value="25000"></property>
        </bean>
    </beans>
    

    集合属性

    在Spring中可以通过一组内置的xml标签(例如:<list>,<set>,<map>)来配置集合属性。

    配置java.util.List类型的属性,需要指定<list>标签,在标签里包含一些元素,这些标签可以通过<value>指定简单的常量值,通过<ref>指定对其他Bean的引用,通过<bean>指定内置Bean定义,通过<null/>指定空元素,甚至可以内嵌其他集合。

    数组的定义和List一样,都使用<list>
    配置java.util.set需要使用<set>标签,定义元素的方法与List一样。

    示例:配置一个java.util.List类型的属性。

    • 我们在com.spring.collection包中新建一个Person类:
    package com.spring.collection;
    
    import java.util.List;
    
    public class Person {
        private String name;
        private int age;
        private List<Car> car;
    
        public List < Car > getCar() {
            return car;
        }
    
        public void setCar(List < Car > car) {
            this.car = car;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", car=" + car +
                    '}';
        }
    }
    
    • 然后在com.spring.collection中新建一个Car类:
    package com.spring.collection;
    
    public class Car {
        private String brand;
        private String corp;
        private int price;
        private int maxSpeed;
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public void setCorp(String corp) {
            this.corp = corp;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
    
        public void setMaxSpeed(int maxSpeed) {
            this.maxSpeed = maxSpeed;
        }
    
        public Car(String brand, String corp, int price) {
            this.brand = brand;
            this.corp = corp;
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Car{" +
                    "brand='" + brand + '\'' +
                    ", corp='" + corp + '\'' +
                    ", price=" + price +
                    ", maxSpeed=" + maxSpeed +
                    '}';
        }
    }
    
    • 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="car4" class="com.spring.collection.Car">
            <constructor-arg value="Audi1" type="java.lang.String"></constructor-arg>
            <constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
            <constructor-arg value="222" type="int"></constructor-arg>
        </bean>
        <bean id="car3" class="com.spring.collection.Car">
            <constructor-arg value="Audi2" type="java.lang.String"></constructor-arg>
            <constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
            <constructor-arg value="111" type="int"></constructor-arg>
        </bean>
    
        <!-- 测试如何配置集合属性-->
        <bean id="person2" class="com.spring.collection.Person">
            <property name="age" value="27"></property>
            <property name="name" value="Cerr"></property>
            <property name="car" >
                <!-- 使用list节点为list类型的属性赋值-->
                <list>
                    <ref bean="car4" />
                    <ref bean="car3" />
                </list>
            </property>
        </bean>
    </beans>
    
    • 主函数如下:
    package com.spring.collection;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Main {
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("person2");
            System.out.println(person);
        }
    }
    

    使用<map>节点来配置,applicationContext.xml文件部分代码:

    <!--配置Map属性值-->
        <bean id="newPerson" class="com.spring.collection.NewPerson">
            <property name="name" value="Rose"></property>
            <property name="age" value="11"></property>
            <property name="cars">
                <map>
                    <entry key="AA" value-ref="car3"/>
                    <entry key="BB" value-ref="car4"/>
                </map>
            </property>
        </bean>
    

    使用<props><prop>节点来为properties属性赋值,applicationContext.xml文件部分代码如下:

    <!-- 配置properties属性值-->
        <bean id="dataSource" class="com.spring.collection.DataSource">
            <property name="properties">
                <props>
                    <prop key="user">root</prop>
                    <prop key="password">123</prop>
                </props>
            </property>
        </bean>
    

    dataSource类代码如下:

    package com.spring.collection;
    
    import java.util.Properties;
    
    public class DataSource {
        private Properties properties;
    
        public Properties getProperties() {
            return properties;
        }
    
        public void setProperties(Properties properties) {
            this.properties = properties;
        }
    
        @Override
        public String toString() {
            return "DataSource{" +
                    "properties=" + properties +
                    '}';
        }
    }
    

    使用utility scheme定义集合

    为了共享集合定义的Bean的引用,可以用util schema的集合标签定义独立的集合Bean。
    applicationContext.xml文件:

    <!-- 配置单例的集合Bean,以供多个bean进行引用 -->
        <util:list id="cars1">
            <ref bean="car3"/>
            <ref bean="car4"/>
        </util:list>
    
        <bean id="person4" class="com.spring.collection.Person">
            <property name="name" value="Jack"></property>
            <property name="age" value="20"></property>
            <property name="car" ref="cars1"></property>
        </bean>
    

    使用p命名空间

    为了简化xml文件的配置,越来越多的xml文件采用属性而非子元素配置信息。

    使用了p命名空间后,可以通过<bean>元素属性的方式来配置Bean的属性。
    例如:

    <!-- 通过p命名空间为bean属性赋值,需要先导入p命名空间-->
        <bean id="person5" class="com.spring.collection.Person" p:age="30" p:name="Queen" p:car-ref="cars1"></bean>
    

    相关文章

      网友评论

          本文标题:Spring学习笔记 | 详解bean的配置(一)

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