zoukankan      html  css  js  c++  java
  • 4.Spring系列之Bean的配置1

    一、配置Bean的两种方式之使用XML配置Bean


    1.基于XML配置Bean-属性注入

    创建一个Bean,该Bean提供了有参构造器

    public class Person {
    
        private String name;public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + "]";
        }
    
    }

    在IOC容器内配置属性注入:

    <?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">
    
        <!-- 
            class:bean的全类名,通过反射创建该bean的实例,要求Bean中必须有无参构造器,否则会报:No default constructor found
            id:IOC容器对象引用该bean的标志,例如:ctx.getBean(hello);返回的就是一个Hello对象,即标识容器中的bean,并且id唯一
            注意:若没有定义id,那么自动使用类名首字母小写为id名称
        -->
        <bean id="person" class="com.spring.model.Person">
         <!-- 注意:这里的name必须和Bean属性的setXXX方法中的XXX同名,否则属性无法赋值 --> <property name="name" value="loose"></property> </bean> </beans>

    测试属性注入:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("person");
            System.out.println(person);
            System.out.println(person.getName());
            /**
             * 运行后输出:
             * Person [name=loose]
             * loose
             */
        }
    }

    说明:

    属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
    属性注入使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值
    属性注入是实际应用中最常用的注入方式

    2.构造器注入,使用构造器初始化不必提供get和set方法

    通过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用,构造器注入在 <constructor-arg> 元素里声明属性, <constructor-arg> 中没有 name 属性
    以上方的Bean类为例,去掉属性的set和get方法,同时创建一个Bean的带参构造器:
    public class Person {
    
        private String name;
        private int age;
    
        public Person() {
            super();
        }
    
        public Person(String name,int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }
    
    }

    在IOC容器内配置构造器注入:

    <?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="com.spring.model.Person">
            <constructor-arg value="loose" index="0"></constructor-arg>
            <constructor-arg value="20" index="1"></constructor-arg>
        </bean>
    </beans>

    测试构造器注入:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("person");
            System.out.println(person);
            /**
             * 运行后输出:
             * Person [name=loose, age=20]
             */
        }
    }

    同时,我们也可以指定构造器参数类型的匹配入参:

    <?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="com.spring.model.Person">
            <constructor-arg value="loose" type="java.lang.String"></constructor-arg>
            <constructor-arg value="20" type="int"></constructor-arg>
        </bean>
    </beans>

    3.工厂方法注入这里就省略,用的很少,有兴趣的自己去找下资料

    4.属性注入的细节

    ①.字面值

    字面值:可用字符串表示的值,可以通过<value>元素标签或value属性进行注入
    <bean id="person" class="com.spring.model.Person">
        <property name="name">
            <value>spring</value>
        </property>
    </bean>

    说明:基本数据类型和封装类、String等类型都可以采用字面值注入的方式。

    ②.若字面值包含特殊符号,可以使用<![CDATA[]]>把字面值包裹起来

    <bean id="person" class="com.spring.model.Person">
       <property name="name">
            <value><![CDATA[<spring]]></value>
       </property>
    </bean>

    这里获取到属性值后,输出的是<string,包含了特殊符号<

    ③.引用其它的Bean

    组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能. 要使 Bean 能够相互访问, 就必须在 Bean 配置文件中指定对 Bean 的引用;在 Bean 的配置文件中, 可以通过 <ref> 元素或 ref  属性为 Bean 的属性或构造器参数指定对 Bean 的引用:
    在这里我们首先创建两个Bean,一个是Person代表人,一个是Mobile代表手机:
    public class Person {
    
        private String name;
        private int age;
    
        private Mobile mobile;
    
        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 Mobile getMobile() {
            return mobile;
        }
    
        public void setMobile(Mobile mobile) {
            this.mobile = mobile;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + ", mobile=" + mobile + "]";
        }
    
    }
    public class Mobile {
    
        private String brand;
        private double price;
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Mobile [brand=" + brand + ", price=" + price + "]";
        }
    
    }

    在IOC容器中配置这两个Bean,并使Person引用Mobile:

    <?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="mobile" class="com.spring.model.Mobile">
            <property name="brand" value="iphone"></property>
            <property name="price" value="5000"></property>
        </bean>
    
        <bean id="person" class="com.spring.model.Person">
            <property name="name" value="loose"></property>
            <property name="age" value="20"></property>
    //这里ref中的mobile为上方配置的Mobile这个Bean的id <property name="mobile" ref="mobile"></property> </bean> </beans>

    测试引用其它的Bean:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("person");
            System.out.println(person);
            // 执行后输出:Person [name=loose, age=20, mobile=Mobile [brand=iphone, price=5000.0]]
        }
    }

    IOC容器中也可以这么配置:

    <?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="mobile" class="com.spring.model.Mobile">
            <property name="brand" value="iphone"></property>
            <property name="price" value="5000"></property>
        </bean>
    
        <bean id="person" class="com.spring.model.Person">
            <property name="name" value="loose"></property>
            <property name="age" value="20"></property>
            <property name="mobile">
                <ref bean="mobile"/> //使用ref标签引用Bean
            </property>
        </bean>
    </beans>

    也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 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进行引用 -->
        <!-- <bean id="mobile" class="com.spring.model.Mobile">
            <property name="brand" value="iphone"></property>
            <property name="price" value="5000"></property>
        </bean> -->
    
        <bean id="person" class="com.spring.model.Person">
            <property name="name" value="loose"></property>
            <property name="age" value="20"></property>
            <property name="mobile">
                <bean class="com.spring.model.Mobile">
                    <property name="brand" value="iphone"></property>
                    <property name="price" value="5000"></property>
                  </bean>
            </property>
        </bean>
    </beans>

    注意:

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

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

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

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

    <bean id="person" class="com.spring.model.Person">
       <property name="name">
         <null></null>
       </property>
      <property name="age" value="20"></property>
    </bean>

    同时,Spring 支持级联属性的配置,为了方便查看,这里再次给出两个Bean,分别是Person和Mobile:

    public class Person {
    
        private String name;
        private int age;
    
        private Mobile mobile;
    
        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 Mobile getMobile() {
            return mobile;
        }
    
        public void setMobile(Mobile mobile) {
            this.mobile = mobile;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + ", mobile=" + mobile + "]";
        }
    
    }
    public class Mobile {
    
        private String brand;
        private double price;
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Mobile [brand=" + brand + ", price=" + price + "]";
        }
    
    }

    在IOC容器配置级联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 id="mobile" class="com.spring.model.Mobile">
            <!-- 这里不配置mobile的属性值 -->
        </bean>
    
        <bean id="person" class="com.spring.model.Person">
            <property name="name" value="loose"></property>
            <property name="age" value="20"></property>
            <property name="mobile" ref="mobile"></property>
            <!-- 以级联的形式注入Bean值 -->
            <property name="mobile.brand" value="nokia"></property>
            <property name="mobile.price" value="2000"></property>
        </bean>
    </beans>

    测试级联程序:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("person");
            System.out.println(person);
            // 执行后输出:Person [name=loose, age=20, mobile=Mobile [brand=nokia, price=2000.0]]
        }
    }

    ⑤.引用集合属性

    在 Spring中可以通过一组内置的 xml 标签(例如: <list>, <set> 或 <map>) 来配置集合属性,配置 java.util.List 类型的属性, 需要指定 <list>  标签, 在标签里包含一些元素. 这些标签可以通过 <value> 指定简单的常量值, 通过 <ref> 指定对其他 Bean 的引用. 通过<bean> 指定内置 Bean 定义. 通过 <null/> 指定空元素. 甚至可以内嵌其他集合,数组的定义和 List 一样, 都使用 <list>,配置 java.util.Set 需要使用 <set> 标签, 定义元素的方法与 List 一样:

    ===>配置List集合属性,以上方的Person和Mobile为例,不同的是Person里面的Mobile变成了List<Mobile>,代表一个人可以多部手机:

    public class Person {
    
        private String name;
    
        private List<Mobile> mobiles;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<Mobile> getMobiles() {
            return mobiles;
        }
    
        public void setMobiles(List<Mobile> mobiles) {
            this.mobiles = mobiles;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", mobiles=" + mobiles + "]";
        }
    
    }
    public class Mobile {
    
        private String brand;
        private double price;
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Mobile [brand=" + brand + ", price=" + price + "]";
        }
    
    }

    在IOC容器中配置两个的引用关系:

    <?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">
    
        <!-- 这里配置多个Mobile Bean,然后被person一个个引用 -->
        <bean id="mobile1" class="com.spring.model.Mobile">
            <property name="brand" value="nokia"></property>
            <property name="price" value="2000"></property>
        </bean>
        
        <bean id="mobile2" class="com.spring.model.Mobile">
            <property name="brand" value="iphone"></property>
            <property name="price" value="5000"></property>
        </bean>
    
        <bean id="person" class="com.spring.model.Person">
            <property name="name" value="loose"></property>
            <property name="mobiles">
                <!-- 使用list标签 -->
                <list>
                    <!-- 分别引入多个Bean -->
                    <ref bean="mobile1"/>
                    <ref bean="mobile2"/>
                </list>
            </property>
        </bean>
    </beans>

    测试Bean中引用List集合属性:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("person");
            System.out.println(person);
            // 执行后输出:Person [name=loose, mobiles=[Mobile [brand=nokia, price=2000.0], Mobile [brand=iphone, price=5000.0]]]
        }
    }

    ===>配置Map集合属性,Java.util.Map 通过 <map> 标签定义, <map> 标签里可以使用多个 <entry> 作为子标签.,每个条目包含一个键和一个值

    仍然是以上面的Bean威力,不同的是集合类型变更为Map,请看下方两个Bean的定义:

    public class Person {
    
        private String name;
    
        private Map<String,Mobile> mobiles;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Map<String, Mobile> getMobiles() {
            return mobiles;
        }
    
        public void setMobiles(Map<String, Mobile> mobiles) {
            this.mobiles = mobiles;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", mobiles=" + mobiles + "]";
        }
    
    }
    public class Mobile {
    
        private String brand;
        private double price;
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            this.brand = brand;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Mobile [brand=" + brand + ", price=" + price + "]";
        }
    
    }

    在IOC容器中配置两个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">
    
        <!-- 这里配置多个Mobile Bean,然后被person一个个引用 -->
        <bean id="mobile1" class="com.spring.model.Mobile">
            <property name="brand" value="nokia"></property>
            <property name="price" value="2000"></property>
        </bean>
        
        <bean id="mobile2" class="com.spring.model.Mobile">
            <property name="brand" value="iphone"></property>
            <property name="price" value="5000"></property>
        </bean>
    
        <bean id="person" class="com.spring.model.Person">
            <property name="name" value="loose"></property>
            <property name="mobiles">
                <!-- 使用map标签 -->
                <map>
                    <entry key="nokia" value-ref="mobile1"></entry>
                    <entry key="iphone" value-ref="mobile2"></entry>
                </map>
            </property>
        </bean>
    </beans>

    测试Bean中引用Map集合属性:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            Person person = (Person) ctx.getBean("person");
            System.out.println(person);
            // 执行后输出:son [name=loose, mobiles={nokia=Mobile [brand=nokia, price=2000.0], iphone=Mobile [brand=iphone, price=5000.0]}]
        }
    }

    ===><props> 定义 java.util.Properties, 该标签使用多个 <prop> 作为子标签.,每个 <prop> 标签必须定义 key 属性:

    我们新建一个Bean,用于模拟从配置文件中读取数据库连接信息:

    public class DataSource {
    
        private Properties properties;
    
        public Properties getProperties() {
            return properties;
        }
    
        public void setProperties(Properties properties) {
            this.properties = properties;
        }
    
    }

    将Bean交给IOC容器管理:

    <?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:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <bean id="dataSource" class="com.spring.model.DataSource">
             <property name="properties">
                  <props>
                     <prop key="user">root</prop>
                     <prop key="password">1234</prop>
                     <prop key="jdbcUrl">jdbc:mysql:///test</prop>
                     <prop key="driver">com.mysql.jdbc.Driver</prop>
                  </props>
           </property>
        </bean>
    </beans>

    测试程序:

    public class Main {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            DataSource ds = (DataSource) ctx.getBean("dataSource");
            System.out.println(ds.getProperties());
            //执行后输出:{user=root, password=1234, driver=com.mysql.jdbc.Driver, jdbcUrl=jdbc:mysql:///test}
        }
    }

    注意:

    引用集合属性都存在一个问题,不能将集合作为独立的 Bean 定义, 导致其他 Bean 无法引用该集合, 所以无法在不同 Bean 之间共享集合,但是可以使用 util schema 里的集合标签定义独立的集合 Bean;

    需要注意的是,必须在 <beans> 根元素里添加 util schema 定义:导入util命名空间:xmlns:util="http://www.springframework.org/schema/util"

    配置独立的外部list:

    <util:list id="mobiles">
      <ref bean="mobile1"/>
      <ref bean="mobile2"/>
    </util:list>

    引用独立的外部list:

    <bean id="person" class="com.sring.model.Person">
        <property name="name" value="loose"></property>
        <property name="mobiles" ref="mobiles"></property>
    </bean>

    为了简化 XML 文件的配置,越来越多的 XML 文件采用属性而非子元素配置信息,Spring 从 2.5 版本开始引入了一个新的 p 命名空间,可以通过 <bean> 元素属性的方式配置 Bean 的属性,使用 p 命名空间后,基于 XML 的配置方式将进一步简化:

    <bean id="person" class="com.spring.model.Person"
    p:mobile-ref="mobiles" p:name="loose"></bean>
  • 相关阅读:
    React生命周期, 兄弟组件之间通信
    React组件式编程Demo-用户的增删改查
    React之this.refs, 实现数据双向绑定
    CCF CSP 201812-4 数据中心
    CCF CSP 201812-4 数据中心
    PAT 顶级 1020 Delete At Most Two Characters (35 分)
    PAT 顶级 1020 Delete At Most Two Characters (35 分)
    Codeforces 1245C Constanze's Machine
    Codeforces 1245C Constanze's Machine
    CCF CSP 201712-4 行车路线
  • 原文地址:https://www.cnblogs.com/Json1208/p/8726951.html
Copyright © 2011-2022 走看看