spring配置和管理bean

Spring 管理 Bean-IOC

在 beans.xml 中,我们注入 2 个 Monster 对象, 但是不指定 id
<bean class="com.hspedu.spring.beans.Monster" >
<property name="monsterId" value="1010"/>
<property name="name" value="张三~"/>
<property name="skill" value="呼呼~"/>
</bean>
<bean class="com.hspedu.spring.beans.Monster">
<property name="monsterId" value="666"/>
<property name="name" value="里斯~~!!"/>
<property name="skill" value="giao~~"/>
</bean>
问题 1:运行会不会报错
答:不会报错,会正常运行
问题 2:如果不报错, 你能否找到分配的 id, 并获得到该对象.
答:系统会默认分配 id ,分配 id 的规则是 全类名#0 , 全类名#1 这样的规则来分配 id, 我们可以通过 debug 方式来查看
 
Bean 管理包括两方面——创建 bean 对象 和 给 bean 注入属性
Bean 配置方式包括两方面 —— 基于 xml 文件配置方式 和 基于注解方式

基于 XML 配置 bean

通过类型来获取 bean

细节说明:
1. 按类型来获取 bean, 要求 ioc 容器中的同一个类的 bean 只能有一个, 否则会抛出异常NoUniqueBeanDefinitionException
2. 这种方式的应用场景:比如 XxxAction/Servlet/Controller, 或 XxxService 在一个线程中只需要一个对象实例(单例)的情况
3. 在容器配置文件(比如 beans.xml)中给属性赋值, 底层是通过setter 方法完成的, 这也是为什么我们需要提供 setter 方法
<!--解读:
    1.beans.xml中可以配置多个bean(一个bean标签表示一个Java对象),这里配置一个hero对象的JavaBean
    2.class属性写类的全路径 => 用于spring底层反射创建对象
    3.<bean class="com.recorder.spring.bean.Hero" id="hero01">
    id表示该bean对象在spring容器中的id,可以通过id获取容器中的对象
    4.<property name="id" value="1"></property> value用于给对象的实行赋值
    -->

通过构造器来配置 bean

因为类不可能有完全相同类型和顺序的构造器,所以可以通过type来指定

<!-- 在 spring 的 ioc 容器, 可以通过构造器来配置 bean 对象 -->
    <bean class="com.recorder.spring.bean.Hero" id="hero03">
        <!--1.下标方式-->
        <!--这里的index表示构造器的第几个参数,从0开始计算
        除了index还可以通过name和type来配置-->
        <constructor-arg value="3" index="0"></constructor-arg>
        <constructor-arg value="刘备" index="1"></constructor-arg>
        <constructor-arg value="仁德" index="2"></constructor-arg>

    </bean>
    <bean class="com.recorder.spring.bean.Hero" id="hero04">
        <!--2.数据类型方式-->
        <constructor-arg value="诸葛亮" type="java.lang.String"/>

    </bean>
    <bean class="com.recorder.spring.bean.Hero" id="hero004">
        <!--2.name类型方式-->
        <constructor-arg value="3" name="id"/>
        <constructor-arg value="神诸葛亮" name="name"/>
        <constructor-arg value="七星" name="skill"/>

    </bean>

 

使用细节
1. 通过 index 属性来区分是第几个参数
2. 通过 type 属性来区分是什么类型(按照顺序)
 

通过 p 名称空间配置 bean

<!--通过p命名空间来创建-->
    <!--将光标放在p , 输入alt+enter , 就会自动的添加xmlnamesapce-->
    <bean class="com.recorder.spring.bean.Hero" id="hero05"
          p:id="5"
          p:name="吕布"
          p:skill="无双"
    />

 

通过 ref 来实现 bean 对象的相互引用(体现依赖注入——一个属性依赖于另一个属性)

<!--通过 ref 来实现 bean 对象的相互引用-->
    <!-- bean 对象的相互引用
    1. 其它含义和前面一样
    2. ref 表示 memberDAO 这个属性将引用/指向 id = memberDAOImpl 对象 
    3.注意在spring容器中,是作为一个整体来执行的,引用bean对象时对配置的顺序没有要求(所以这里将vmemberDAO放到MemberServiceImpl后面配置也没有问题,但建议按照顺序写来保证阅读方便)-->
    
    <bean class="com.recorder.spring.dao.MemberDAOImpl" id="memberDAO"/>
    <bean class="com.recorder.spring.service.MemberServiceImpl" id="memberService">
        <property name="memberDAO" ref="memberDAO"/>
    </bean>

 

通过观察容器结构也可以确定

       

引用/注入内部 bean 对象

 <!--也可以通过内部bean的方式-->
    <bean class="com.recorder.spring.service.MemberServiceImpl" id="memberService2">
        <property name="memberDAO">
            <bean class="com.recorder.spring.dao.MemberDAOImpl" id="memberDAO"/>
        </property>
    </bean>

 这里不再是引用外部的bean对象,而是直接在自己的内部配置一个内部bean

 

引用/注入集合/数组类型

 <!--配置master bean-->
    <bean class="com.recorder.spring.bean.Master" id="master">
        <property name="name">
            <value>紫英</value>
        </property>
        <property name="heroList">
            <!--配置list-->
            <list>
                <!--可以使用ref依赖-->
                <ref bean="hero01"></ref>
                <ref bean="hero02"></ref>
                <!--也可以直接使用内部bean-->
                <bean class="com.recorder.spring.bean.Hero">
                    <property name="id" value="6"></property>
                    <property name="name" value="赵云"></property>
                    <property name="skill" value="龙胆"></property>
                </bean>
            </list>
        </property>
        <!--配置map属性-->
        <property name="heroMap">
            <!--先来个map标签-->
            <map>
                <!--map中配置各个entry-->
                <entry>
                    <!--entry中配置对应的key和value-->
                    <key>
                        <!--意思是key的值是hero03-->
                        <value>hero03</value>
                    </key>
                    <!--value的值,可以使用依赖或者内部bean-->
                    <ref bean="hero03"></ref>
                </entry>
                <entry>
                    <key>
                        <value>hero04</value>
                    </key>
                    <ref bean="hero04"></ref>
                </entry>
            </map>
        </property>
        <!--给set赋值-->
        <property name="heroSet">
            <!--跟list差不多,这里使用ref引用-->
            <set>
                <ref bean="hero01"></ref>
                <bean class="com.recorder.spring.bean.Hero">
                    <property name="id" value="7"></property>
                    <property name="name" value="貂蝉"></property>
                    <property name="skill" value="离间"></property>
                </bean>
            </set>

        </property>

        <!--给数组赋值-->
        <property name="heroName">
            <array>
                <!--array标签中直接使用value还是其他要看数组的类型,
                如果是引用类型可以使用bean或者ref-->
                <value>along</value>
                <value>小丁猫</value>
            </array>
        </property>

        <!--给properties属性赋值-->
        <!--注意properties的key和v都是string类型的-->
        <property name="pros">
            <props>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
                <prop key="ip">192.168.66.66</prop>
            </props>
        </property>
    </bean>

Master{name='紫英', HeroList=[Hero{id=1, name='李白', skill='青莲剑歌'}, Hero{id=2, name='韩信', skill='国士无双'}, Hero{id=6, name='赵云', skill='龙胆'}], HeroMap={hero03=Hero{id=3, name='刘备', skill='仁德'}, hero04=Hero{id=null, name='诸葛亮', skill='null'}}, HeroSet=[Hero{id=1, name='李白', skill='青莲剑歌'}, Hero{id=7, name='貂蝉', skill='离间'}], HeroName=[along, 小丁猫], pros={password=123456, ip=192.168.66.66, username=root}}
使用细节
1. 主要掌握 List/Map/Properties 三种集合的使用.
2. Properties 集合的特点:
1) 这个 Properties 是 Hashtable 的子类 , 是 key-value 的形式
2) key 是 string 而 value 也是 string

通过 util 名称空间创建 list

<!--通过util:list命名空间来实现数据复用-->
    <util:list id="myBookList">
        <value>西游记</value>
        <value>水浒传</value>
        <value>红楼梦</value>
        <value>三国演义</value>
    </util:list>
//优点————如果有别的bean使用这个booklist就可以直接引用,实现数据复用和共享
<bean class="com.recorder.spring.bean.BookStore" id="bookStore"> <property name="bookList" ref="myBookList"/> </bean>

级联属性赋值

spring 的 ioc 容器, 可以直接给对象属性的属性赋值, 即级联属性赋值
dept:部门 emp:职员  
 <!--通过级联属性赋值-->
    <bean class="com.recorder.spring.bean.Dept" id="dept"></bean>
    <bean class="com.recorder.spring.bean.Emp" id="emp">
        <property name="name" value="along"></property>
        <property name="dept" ref="dept"></property>
        <!--这里底层会调用dept对象的setName方法去赋值-->
        <property name="dept.name" value="java开发"></property>
    </bean>

 

 

通过静态工厂获取对象

先创建一个静态工厂

public class MyStaticFactory {
    //静态代码块——随着类的加载而加载,并且只执行一次
    private static Map<String, Hero> heroMap;
    //通过静态代码块进行初始化
    static {
        heroMap = new HashMap<>();
        heroMap.put("hero001",new Hero(1,"孙悟空","金箍棒"));
        heroMap.put("hero002",new Hero(2,"猪八戒","九齿钉耙"));
    }
    public static Hero getHero(String key){
        return heroMap.get(key);
    }

}

配置xml文件

<!--通过静态工厂获取hero/配置bean
    解读:
    1.class的路径不是hero的而是静态工厂类的
    2.factory-method表示返回hero对象的静态工厂类的方法
    3.constructor-arg value="hero001" value表示返回静态工厂类的哪个对象
    -->
    <bean class="com.recorder.spring.factory.MyStaticFactory"
          id="my_hero01"
          factory-method="getHero">
        <constructor-arg value="hero001"></constructor-arg>
    </bean>

通过实例工厂获取对象

 先创建一个实例工厂类

import com.recorder.spring.bean.Hero;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 紫英
 * @version 1.0
 * @discription 实例工厂类——可以创建或返回hero对象
 */
public class MyInstanceFactory {

    private Map<String, Hero> heroMap;

    //通过普通代码块进行初始化——每创建一个MyInstanceFactory实例普通代码块接会被执行一次
    //但是在配置文件中同一个id在容器中就对应着同一个实例工厂,所以是同一个对象,
    // 不同id的情况下就不是同一个对象
    {
        heroMap = new HashMap<>();
        heroMap.put("hero003", new Hero(3, "孙悟空~~", "金箍棒~~"));
        heroMap.put("hero004", new Hero(4, "猪八戒~~", "九齿钉耙~~"));
    }

    public Hero getHero(String key) {
        return heroMap.get(key);
    }

}

配置xml文件

<!--先配置一个实例工厂对象——因为静态类不用创建实例就可以调用方法,普通类则不行-->
    <bean class="com.recorder.spring.factory.MyInstanceFactory" id="myInstanceFactory"/>
    <!--通过实例工厂获取hero/配置bean
    解读:
    1.factory-bean表示指定哪个实例工厂
    2.factory-method表示返回hero对象的实例工厂类的方法
    3.constructor-arg value="hero004" value表示返回实例工厂类的哪个对象
    -->
    <bean id="my_hero02" factory-bean="myInstanceFactory" factory-method="getHero">
        <constructor-arg value="hero004"></constructor-arg>
    </bean>

通过 FactoryBean 获取对象(重点)

package com.recorder.spring.factory;

import com.recorder.spring.bean.Hero;
import org.springframework.beans.factory.FactoryBean;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 紫英
 * @version 1.0
 * @discription 通过 FactoryBean 获取对象(重点)
 */
public class MyFactoryBean implements FactoryBean<Hero> {
    private String key;//配置xml文件时,指定要获取的对象的key

    public void setKey(String key) {
        this.key = key;
    }

    private Map<String,Hero> heroMap;
    {
        heroMap = new HashMap<>();
        heroMap.put("hero003", new Hero(3, "孙悟空~~", "金箍棒~~"));
        heroMap.put("hero004", new Hero(4, "猪八戒~~", "九齿钉耙~~"));
    }
    @Override
    public Hero getObject() throws Exception {
        return heroMap.get(key);
    }

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

    @Override
    //返回的是否是单例对象
    public boolean isSingleton() {
        return true;
    }
}

配置xml文件

<!--通过FactoryBean配置hero对象-->
    <bean id="my_hero03" class="com.recorder.spring.factory.MyFactoryBean">
        <!--这里的key就是MyFactoryBean中的属性key-->
        <property name="key" value="hero003"></property>
    </bean>

bean 配置信息重用(继承)

<!--bean的继承(复用)
    abstract="true"表示该bean只能被继承,不能被实例化,否则会报错-->
    <bean class="com.recorder.spring.bean.Hero" id="hero06" abstract="true">
        <!--1.下标方式-->
        <property name="id" value="6"></property>
        <property name="name" value="曹仁"></property>
        <property name="skill" value="解围"></property>
    </bean>
    <!--parent="hero06"表示id为hero07的bean的属性继承自hero06-->
    <bean class="com.recorder.spring.bean.Hero" id="hero07" parent="hero06"/>

 

posted @ 2022-10-17 15:34  紫英626  阅读(153)  评论(0编辑  收藏  举报

紫英