【spring框架 02】

一、集合属性

场景:对象的属性是集合类型的,那么就需要注入一个集合

实现方式:在Spring中可以通过一组内置的XML标签来配置几个属性,例如:<list>,<set>或<map>

1、list集合、set集合、数组属性赋值

案例:

1)创建一个PersonList类,有name和list<Car> 两个私有属性

2)IOC容器给属性赋值

<!--list集合、set集合、数组-->
    <bean id="personlist" class="com.wufq.spring.PersonList">
        <property name="name" value="韦小宝"></property>
        <property name="car">
            <!--构造集合-->
            <list>
                <!--两中方式赋值:内部bean、ref-->
                <ref bean="car"></ref>
                <ref bean="car1"></ref>
                <ref bean="car2"></ref>
                
                <!--数组对象有自己特有的标签,但是可以直接用list(建议用)-->
                <!--<array></array>-->
                <!--set集合可以直接用set标签-->
                <!--<set></set>-->

            </list>
        </property>
    </bean>

3)调用测试

  @Test
    public void testList(){
        PersonList list = context.getBean("personlist", PersonList.class);
        System.out.println(list);

    }
=====执行结果====
PersonList{name='韦小宝', car=[Car{brand='奔驰', crop='一汽', price='400000.0',speed='500'}, Car{brand='奥迪', crop='一汽', price='450000.0',speed='null'}, Car{brand='宝马', crop='华晨', price='0.0',speed='200'}]}

 2、map集合属性赋值

    <!--map集合-->
    <bean id="personMap" class="com.wufq.spring.PersonMap">
        <property name="name" value="小昭"></property>
        <property name="map">
            <!--构造map-->
            <map>
                <entry key="AA" value-ref="car"></entry>
                <entry key="BB" value-ref="car1"></entry>
                <entry key="CC" value-ref="car2"></entry>
            </map>
        </property>
    </bean>

注意点:给map集合属性的值赋值,用到<map></map>标签,map集合是无法直接取值的,所以需要转换成set集合,这时候就用到了entry,同样在map集合属性赋值也用到<entry>

以及通过entry内部的key和value进行赋值

3、集合类型的bean (主要解决没有可引用的bean)

就是把集合设置成共有的,供其他所有的bean使用。

-->前提:配置集合类型的bean需要引入util名称空间

1)idea需要引入spring的命名空间(无法像eclipse一样勾选Namespaces),需要手动添加util的空间名称

#在xml文件的首部添加
xmlns:context="http://www.springframework.org/schema/context"
然后我们打出:xmlns:util= 然后就会有相应的以提示,完整的内容如下: xmlns:util="http://www.springframework.org/schema/util"

注意:xmlns:util  或者xmlns:p必须在xmlns:context="”这一行的下面打,否则也不会提示

2)在xsi:schemaLocation=内补充

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd

注意:http://.../spring-context.xsd必须要写并且放在http://.../scontext下面,否则会报“无法找到元素context:component-scan”错

     http://.../spring-util-4.0.xsd必须要写并且放在http://.../util下面,否则会报“无法找到元素 'util:map' 的声明”错

-->配置集合类型的bean

<!--集合bean-->
    <util:map id="mapBean">
        <entry key="AA" value-ref="car"></entry>
        <entry key="BB" value-ref="car1"></entry>
        <entry key="CC" value-ref="car2"></entry>
    </util:map>

    <util:list id="listBean">
        <ref bean="car"></ref>
        <ref bean="car1"></ref>
        <ref bean="car2"></ref>
    </util:list>

========其他bean引用集合bean=========
<bean id="personMap" class="com.wufq.spring.PersonMap">
        <property name="name" value="小昭"></property>
        <property name="map" ref="mapBean"></property>
    </bean>

二、FactoryBean

  • spring中有两种类型的bean,一种是普通的bean(上面讲的那种)另外一种是工厂bean,即FactoryBean
  • 工厂bean跟普通bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂bean的getObject方法锁返回的对象
  • 工厂bean必须实现org,springframework.bean.factory.FactoryBean接口

#案例:通过FactoryBean实现对Car类的属性赋值

1)创建一个FactoryBeanTest类实现FactoryBean接口

package com.wufq.factorySpring;

import com.wufq.spring.Car;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author wufq
 * @Date 2021/4/8 15:39
 */
public class FactoryBeanTest implements FactoryBean<Car> {
    /*
    * FactoryBean具体创建的bean对象是由getObject()方法来返回的
    * 当前案例:FactoryBean<T>接口内的类型是Car类型,所以需要返回Car类型的对象
    * */

    @Override
    public Car getObject() throws Exception {
        return new Car("扣扣","宝马",50000);
    }

    /*
    * 返回具体bean对象的类型
    * */

    @Override
    public Class<?> getObjectType() {
        return Car.class;
    }

    /*
    * bean可以是单例的,也可以是原型的(非单例)
    * */

    @Override
    public boolean isSingleton() {
        return false;
    }

}

 2)创建spring的xml配置文件:factoryBean-di.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">

    <!--通过FactoryBean来配置

        FactoryBean具体返回的对象由getObject方法来决定
    -->
    <bean id="factoryBean" class="com.wufq.factorySpring.FactoryBeanTest"></bean>


</beans>

3)在FactoryBeanTest类内通过main测试

 public static void main(String[] args){
        ApplicationContext con = new ClassPathXmlApplicationContext("factoryBean-di.xml");
        Car car = con.getBean("factoryBean", Car.class);
        System.out.println(car);
    }

=====执行结果=====
Car{brand='扣扣', crop='宝马', price='50000.0',speed='null'}

理解:普通bean是通过缺省构造器和构造方法来创建对象的,比较被动。而FactoryBean  创建的目的是Spring支持我们参与到bean对象的创建过程中,这样会灵活一些

 三、bean的高级配置

1、bean和bean之间的继承关系(关键字:parent

#案例 :实现address1继承address2的bean

1)创建一个Address类,有city和Street(街道)两个属性

2)创建spring的xml文件:spring-relation.xml

<!--bean的继承关系-->
    <bean id="address1" class="com.wufq.relation.Address">
        <property name="city" value="beijing"></property>
        <property name="street" value="chaoyangjie"></property>
    </bean>

    <!--因为address2内class和city属性和address1一样,所以我们可以让address2继承address1来复用address1的class和city

        继承关键字:parent
    -->
    <bean id="address2" parent="address1">
        <property name="street" value="changanjie"></property>
    </bean>

3)创建测试类AddressTest测试address2是否继承了address1的bean

public class AddressTest {

    ApplicationContext context = null;

    @Before
    public void brf(){
        context=  new ClassPathXmlApplicationContext("spring-relation.xml");
    }

    @Test
    public void testAddress(){
        Address add1= context.getBean("address1",Address.class);
        System.out.println("Address1:"+add1);

        Address add2 = context.getBean("address2", Address.class);
        System.out.println("Address2:"+add2);

    }
}

====执行结果====
Address1:Address{city='beijing', street='chaoyangjie'}
Address2:Address{city='beijing', street='changanjie'}
由执行结果Address2可以看出来继承了Address1的

 2、bean也可以实现抽象(关键字abstract

<!-- abstract="true":抽象bean 不能被创建对象,class可以忽略不写

        继承抽象的父bean可以继承一些配置,但是id,abstract,autowire是不能被继承的

        注意:由于抽象bean不能被创建对象,所以测试类的时候不能创建Address1的对象。Address add1= context.getBean("address1",Address.class);
    -->
    <bean id="address1" abstract="true"  >
        <property name="city" value="beijing"></property>
        <property name="street" value="chaoyangjie"></property>
    </bean>

    <!--因为address2内class和city属性和address1一样,所以我们可以让address2继承address1来复用address1的class和city

        继承关键字:parent
    -->
    <bean id="address2" class="com.wufq.relation.Address" parent="address1">
        <property name="street" value="changanjie"></property>
    </bean>

 3、bean之间的依赖关系(关键字:depends-on)

 创建一个bean的时候必须保证另外一个bean也被创建,这时候我们称前面的bean对后面的bean有依赖。

<!--依赖关系-->
    <bean id="address3" class="com.wufq.relation.Address" parent="address1" depends-on="address4">

    </bean>

    <bean id="address4" class="com.wufq.relation.Address"></bean>

“address3”依赖“address4”,如果没有创建address4时就会报错

四、bean的作用域

在<bean>中可以用scope关键字设置作用域,以决定这个bean是单例的还是多例的

|-- singleton:单例的(默认值),在这个IOC容器中只能存在一个bean的对象而且在IOC容器对象被创建时,就创建单例的bean的对象,后续每次通过getBean()方法获取bean对象时,返回的都是同一个对象

#案例演示:

1)创建Car类,包含两个私有属性brand,prices。创建set、get方法,重写toString()方法,创建缺省构造器:内部打印“Ainit car....”

2)创建spring的xml文件,设置作用域为:singleton(默认,可以不写)

 <bean id="car" class="com.wufq.Spring.scope.Car" scope="singleton">
        <property name="brand" value="奥迪"></property>
        <property name="prices" value="500000"></property>

    </bean>

3)创建测试类测试

public class CarTest {

    ApplicationContext context=null;

    @Before
    public void bef(){
        context = new ClassPathXmlApplicationContext("spring-scope.xml");
    }
  
  @Test
  public void testScope1(){}; //Ainit car.... //不获取bean对象,去执行同样会把缺省构造器内的此内容打印出来,说明在singleton模式下,在创建IOC容器时就已经创建了对象

@Test
public void testScope2(){ Car car1 = context.getBean("car", Car.class); Car car2 = context.getBean("car",Car.class); System.out.println(car1==car2); //true -->正常情况下new对象,每个对象都是不一样的,这里两个对象是true说明创建IOC容器的时候就值创建了一个对象,所以在两次获取bean对象都是同一个对象 } }

 |-- prototype:原型的/多例的。在整个IOC容器中可有多个bean的对象在IOC容器对象被创建时,不会创建原型的bean的对象,而是等到每次通过getBean()方法获取bean对象时,才会创建一个新的bean对象

#案例演示:

1)修改spring的xml文件,设置作用域为:prototype

<bean id="car" class="com.wufq.Spring.scope.Car" scope="prototype">
        <property name="brand" value="奥迪"></property>
        <property name="prices" value="500000"></property>

    </bean>

2)测试类测试

public class CarTest {

    ApplicationContext context=null;

    @Before
    public void bef(){
        context = new ClassPathXmlApplicationContext("spring-scope.xml");
    }

    @Test
    public void testScope1(){

    } //没有结果-->说明只创建IOC容器不会创建对象
    @Test
    public void testScope2(){
        Car car1 = context.getBean("car", Car.class);
        Car car2 = context.getBean("car",Car.class);

        System.out.println(car1==car2); //true -->说明创建IOC容器的时候就值创建了一个对象,所以在两次获取bean对象都是同一个对象
    }
/*
打印结果:
Ainit car...
Ainit car...
false
说明只有获取getBean方法时才会创建对象,并且每获取一次就创建一个对象,并且创建的对象不一样
*/
}

 

posted @ 2021-04-07 18:02  尘封~~  阅读(69)  评论(0编辑  收藏  举报