Spring-IOC:复杂值注入、各种类型赋值、bean的复用

复杂值注入准备工作

从这里开始我们要进行复杂值的注入

创建 Car

public class Car {
    // 写入有参无参setget...
    private String carName;
    private Integer price;
    private String color;
}

创建Book

public class Book {
    // 写入有参无参setget...
    private String bookName;
    private Integer price;
}

Person类

public class Person {
    // 写入有参无参setget ToString...
    private String lastName;
    private String gender;
    private Integer age;
    private String email;

    private Car car;
    private List<Book> books;
    private Map<String,Object> maps;
    private Properties properties;
}    

测试空值null

1.当注入bean不赋值

<bean >

</bean>

此时我们仅仅只是注册了 这个bean,但我们是没有进行任何赋值操作的

我们进行打印输出会得到

Person{lastName='null', gender='null', age=null, email='null', car=null, books=null, maps=null, properties=null}

会将他们的默认值输出,即为null

2.设置初始值

但此时我将Person 中的lastName设置初始值 "小姜"

public class Person {
    private String lastName = "小姜";
    ......

再次进行输出

Person{lastName='小姜', gender='null', age=null, email='null', car=null, books=null, maps=null, properties=null}

那么打印出来的话,则是 lastname="小姜"....
但如果我此时 我希望默认值小姜变成null 怎么做

<bean >
	可以在这里使用porperty进行赋值
    <property name="lastName" value="null"></property>
</bean>

此时打印

Person{lastName='null', gender='null', age=null, email='null', car=null, books=null, maps=null, properties=null}

好像是变成了lastname=null

但是当我们进行判断

Person person01 = app.getBean("person01", Person.class);
System.out.println(person01.getLastName() == null);

输出false 即不是真正的null 只是一个字符串null而已

3.解决方法

<bean >
	可以在这里使用porperty进行赋值
    <!-- <property name="lastName" value="null"></property> -->
    通过null 标签进行设置空值
	<property name="lastName">
		<null/>
    </property>
</bean>

复杂类型的赋值 在标签体里进行赋值

System.out.println(person01.getLastName() == null);

此时判断则为true

ref引入外部bean

ref :引用外面的值

<beans>	
	<bean >
   	 	<property name="car" ref="car01"></property>
	</bean>

    <!--2.ref引用的car-->
    <bean >
        <property name="carName" value="milk"></property>
        <property name="color" value="white"></property>
        <property name="price" value="2000"></property>
    </bean>
</beans>

那么我们在person对象里 有private Car car 也就是在Person类中有Car对象

我们之前通过property赋值 ,都是赋给某个属性的值 :比如 name、age..... 那么我们此时如何赋给对象值呢

我们可以先将我们的car对象注册为一个bean 然后通过ref 引用我们这个bean

注意点:

​ 1.我们在这里的ref 就是引用的下面car01的值

​ 2.这个car 虽然是person01中的car,但其实他是引用的ioc容器中的car01

​ 3.所以car == car01 当car01进行修改时,car的值也会随着改变


引入内部bean

其实就是在我们person01下 new了一个新的car对象

<beans >
    <bean >
        <!--3.bean标签在内部创建
            直接就是在这个person01下面新new了一个car对象
              -->
        <property name="car">
            <bean >
                <property name="price" value="200"></property>
                <property name="color" value="black"></property>
                <property name="carName" value="mmm~"></property>
            </bean>
        </property>
    </bean>
</beans>

很简单 我们的car是个对象 不是个属性

那么我们就在property里注册一个新的bean


List类型赋值

1.在list标签中添加元素

    <bean >
        <property name="books">
           
            <list>
                <!--list标签中添加一个元素-->
                <bean class="com.jiang.bean.Book">
                    <property name="price" value="50"></property>
                    <property name="bookName" value="Spring5核心原理"></property>
                </bean>
            </list>
        </property>
    </bean>

<list></list> 其实就是books = new ArrayList<Book>()

为books赋值 就说向list集合books中添加元素

第一种方法就是直接通过bean标签 添加属性值 比较简单

2.ref引用

<bean >
    <property name="bookName" value="高性能Netty"></property>
    <property name="price" value="55"></property>
</bean>

<bean >
    <property name="books">
        <!--books = new ArrayList<Book>()-->
        <list>
            <!--list标签中添加一个元素-->
            <bean class="com.jiang.bean.Book">
                <property name="price" value="50"></property>
                <property name="bookName" value="Spring5核心原理"></property>
            </bean>
            <!--ref引用-->
            <ref bean="book"></ref>
        </list>
    </property>
</bean>

首先在外面注册一个book的bean 赋于对应的值

然后在list内部 通过ref引用外面注册的这个bean 即ref引用的book

记得写法是 ref bean="book"

PS: 内部写的bean是不需要name的
你在beans下,也就是外面的bean是全局的 大家都可以用 你写name可以输出打印
但是你在property下的bean是内部的,不可以被随便打印,所以不需要name


Map类型赋值

<property name="maps">
    <!--map = new LinkedHashMap()-->
    <map>
        <!--一个entry 就代表一个键值对-->
        <entry key="key01" value="张三"></entry>
        <entry key="key02" value="18"></entry>
        <entry key="key03" value-ref="book"></entry>
        <entry key="key04">
            <bean class="com.jiang.bean.Book">
                <property name="bookName" value="SpringBoot实战开发"></property>
            </bean>
        </entry>
        <entry key="key05">
            <map></map>
        </entry>
    </map>
</property>

当你在property下,写一个map标签时,其实在底层就是给你new 了一个LinkedHaskMap()

每个entry 都代表一个键值对

  • 第一种方式就是 <entry key="键名" value="值">
  • 第二种方式是 key键名不变,值通过value-ref引入外面的值
  • 第三种方式是 在entry标签内部,键名不变,值是通过bean标签重新注入
  • 第四种方式是在map里集成map.....用的不多 省略

Properties

<property name="properties">
    <!--props = new Properties() -->
    <props>
        <!--所有的key=value 都是String类型 所以值都写在标签体中-->
        <prop key="username" >root</prop>
        <prop key="password">123456</prop>
    </props>
</property>

当你在property下,写一个props标签时,其实在底层就是给你new 了一个Properties()

所有的key=value 都是String类型 所以值都写在标签体中


util方式的map引用

1.引入util命名空间

<?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:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-4.1.xsd">

2.在bean标签外创建util标签

    <util:map >
        <!--一个entry 就代表一个键值对-->
        <entry key="key01" value="王五"></entry>
        <entry key="key02" value="18"></entry>
        <entry key="key03" value-ref="book"></entry>
        <entry key="key04">
            <bean class="com.jiang.bean.Book">
                <property name="bookName" value="SpringBoot实战开发"></property>
            </bean>
        </entry>
        <entry key="key05">
            <map></map>
        </entry>

    </util:map>

Ps:我们这个util:map 是可以在全局进行访问的

3.map通过ref引入

<property name="maps" ref="utilmap"></property>

级联属性赋值

级联属性:属性的属性 比如Car.price

<bean >
    <!-- 为car赋值的时候 我要改变price -->
    <property name="car" ref="carbean"></property>
    <!--我们可以通过car.price 进行单独的修改 -->
    <property name="car.price" value="150"></property>
    <!--但是此时就出现了问题,我们发现无论是ioc中的car还是person03中的car的price都进行了改变
        这是因为我们获取car的方式是引用,所以我们进行修改的时候,其实是修改的引用地址的那个price
        所以级联属性可以对属性的属性进行修改,但可能会改变原来的值
        -->
</bean>
  • 我们可以通过car.price 进行单独的修改
  • 但是此时就出现了问题,我们发现无论是ioc中的car还是person03中的car的price都进行了改变
  • 这是因为我们获取car的方式是引用,所以我们进行修改的时候,其实是修改的引用地址的那个price
  • 所以级联属性可以对属性的属性进行修改,但可能会改变原来的值

继承实现bean的复用

<bean >
    <property name="lastName" value="马云"></property>
    <property name="age" value="50"></property>
    <property name="email" value="123456@alibaba.com"></property>
    <property name="gender" value="男"></property>
    
</bean>

此刻 我们希望有一个person02 他的属性值和person01相同

<!--parent:指定当前bean的配置信息继承于那个-->
<bean ></bean>

我们就可以使用parent属性

parent:指定当前bean的配置信息继承于那个

如果我们只希望person01只允许被继承,不允许被获取实例怎么办?

我们可以通过 abstrac=true来实现这个效果

<bean >
    <property name="lastName" value="马云"></property>
    <property name="age" value="50"></property>
    <property name="email" value="123456@alibaba.com"></property>
    <property name="gender" value="男"></property>
</bean>