在IoC容器中装配Bean(基于XML配置)

一、Bean的命名

一般情况下,必须为Bean指定id,id必须唯一不能重复,如果使用name属性,可以重复。也可以使用匿名的bean。强烈建议通过id指定Bean。

name="#car1,123,$car" class="com.smart.simple.Car"/>

如果同一个Bean使用了相同的name,那么getBean(beanName)获取Bean时,会返回后面声明的那个Bean。
如果id和name都没有指定,只指定了全类名如:

<bean class="com.smart.simple.Car"/>
<bean class="com.smart.simple.Car"/>
<bean class="com.smart.simple.Car"/>

第一个Bean可以通过getBean(“com.smart.simple.Car”)获得,第二个Bean通过getBean(“com.smart.simple.Car#1”)获得。第三个Bean通过getBean(“com.smart.simple.Car#2”)获得。

二、依赖注入

2.1 属性注入

属性注入通过setXxx()方法注入Bean的属性值或依赖对象,需要注意的是,Bean中不一定有xxx属性,只是需要提供setter方法。变量的前两个字母要么全部大写,要么全部小写。代码略。。

2.2 构造函数注入

2.2.1 按类型匹配入参
public class Car{
    private String brand;
    private double price
    public Car(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }
}

"car1" class="com.smart.simple.Car">
    "java.lang.String" value="红旗CA72"/>
    "double" value="20000"/>
2.2.2 按索引匹配入参
public Car(String brand,String corp,double price){
    this.brand=brand;
    this.corp=corp;
    this.price=price;
}

"car2" class="com.smart.simple.Car">
    "0" value="红旗CA72"/>
    "1" value="中国一汽"/>
    "2" value="20000"/>
2.2.3 联合使用类型和索引匹配入参
public Car(String brand,String corp,double price){
    ...
}
public Car(String brand,String corp,int maxSpeed){
    ...
}

"car3" class="com.smart.simple.Car">
    "java.lang.String" index="0" value="红旗CA72"/>
    "java.lang.String" index="1"  value="中国一汽"/>
    "int" index="2"  value="20000"/>
2.2.4 通过自身类型反射入参
public Boss(String name,Car car,Office office){
    ...
}

"boss" class="com.smart.simple.Boss">
    "John"/>
    "car"/>
    "office"/>
2.2.5 循环依赖问题

由于两个bean都采用构造函数注入,且都通过构造函数入参引用对方,就会发生循环依赖问题。如果存在循环依赖问题,Spring容器将无法启动,解决办法是将狗仔函数注入改为属性注入就可以了。

public Car(String brand,Boss boss){
}
public Boss(String name,Car car){
}

"car4" class="com.smart.simple.Car">
    "0" value="红旗CA72"/>
    "1" ref="boss"/>

"boss" class="com.smart.simple.Boss">
    "0" value="Jone"/>
    "1" ref="car"/>

2.3 工厂方法注入

2.3.1 非静态工厂方法
public class CarFactory{
    public Car createHongQiCar(){
        Car car=new Car();
        car.setBrand("红旗CA72");
        return car;
    }
}

"carFactory" class="com.smart.factory.CarFacotry"/>
"car5" factory-bean="carFactory" factory-method="createHongQiCar" />
2.3.2 静态工厂方法
"car6" class="com.smart.factory.CarFactory" factory-method="createCar" />
//class指工厂类,factory-method指工厂类方法

三、注入参数详解

3.1 字面值

当在xml配置文件中使用(< > & ” ‘)五种符号时,要注意特殊处理:其一使用特殊标签,其二是使用xml转义序列表示这些特殊字符:红旗&72

3.2 引用其他Bean

public class Boss{
    public void setCar(Car car){
        this.car=car;
    }
}

"car" class="com.smart.simple.Car"/>
"boss" class="com.smart.simple.Boss">
    
        <ref bean="car">ref>
    

/*
ref元素通过以下3个属性引用容器中的其他bean:
bean:通过该属性可以引用统一容器或父容器中的bean,这是最常见的形式
local:只能引用同一配置文件中定义的bean。
parent:引用父容器中的bean
*/

3.3 内部bean

如果一个Bean只想被一个Bean引用,二不被容器中任何其他的Bean引用,则可以将Bean以内部Bean的方式注入。

id="boss" class="com.smart.simple.Boss">
    <property name="car">
        class="com.smart.simple.Car" p:maxSpeed="200" p:price="20000"/>
    property>

3.4 null值

<property name="brand"><null/>property>

3.5 级联属性

<bean id="boss3" class="com.smart.simple.Boss" >
    <property name="car.brand" value="吉利CT40"/>
bean>
//注意car非空

3.6 集合类型属性

3.6.1 List

public class Boss{
    public List favorites=new ArrayList();
    public void setFavorites(List favorites){
        this.favorites=favorites;
    }
}

"boss1" class="com.smart.simple.Boss">
    "favorites">
        
            <value>看报value>
            <value>游泳value>
            <value>打球value>
        
    

3.6.2 Map

private Map jobs=new HashMap();
public void setJobs(Map jobs){
    this.jobs=jobs;
}
"boss1" class="com.smart.simple.Boss">
    "jobs">
        
            "AM" value="会见客户" />
            "PM" value="内部会议" />
        
    

3.6.3 Set

<bean id="boss1" class="com.smart.simple.Boss">
    <property name="favorites">
        <set>
            <value>看报value>
            <value>游泳value>
            <value>打球value>
        set>
    property>
bean>

3.6.4 Properties

private Properties mails=new Properties();
public void setMails(){}

<bean id="boss1" class="com.smart.simple.Boss">
    <property name="mails">
        <props>
            <prop key="jobMail">[email protected]prop>
            <prop key="lifeMail">[email protected]prop>
        props>
    property>
bean>

3.6.5 强类型集合
与非强类型集合配置相同。
3.6.6 集合合并

<bean id="boss1" class="com.smart.simple.Boss" abstract="true"> 
    <property name="favorites">
        <set>
            <value>看报value>
            <value>游泳value>
            <value>打球value>
        set>
    property>
bean>
<bean id="childBoss" parent="boss1"> 
<property name="favorites">
<set merge="true"> 
<value>爬山value>
<value>逛街value>
set>
property>
bean>

3.6.7 通过util命名空间配置集合类型的bean
引入util的命名空间声明。


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p"
    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.3.xsd                http://www.springframework.org/schema/util              http://www.springframework.org/schema/util/spring-util-4.3.xsd">
    <util:list id="favoritesList" list-class="java.util.LinkedList">
        <value>看报value>
        <value>赛车value>
        <value>高尔夫value>
    util:list>

    <util:set id="favoriteSet">
        <value>看报value>
        <value>赛车value>
        <value>高尔夫value>
    util:set>

    <util:map id="email">
        <entry key="AM" value="会见客户">entry>
        <entry key="PM" value="内部会议">entry>
    util:map>
beans>

四、方法注入

用处:向singleton的Bean中注入prototype的Bean,一种方法是让singleton实现BeanFactoryAware接口。下面是其余两种方法。

4.1 lookup方法注入

public interface MaginBoss{
    //通过getBean()返回prototype的Bean,每次都返回新实例
    Car getCar
}


<bean id="car" class="com.smart.simple.Car" p:brand="红旗" p:price="20000" scope="prototype"/>

<bean id="magicBoss" class="com.smart.simple.MagicBoss">
    <lookup-method name="getCar" bean="car"/>
bean>

4.2 方法替换

使用某个Bean的方法替换另外一个Bean的方法

public class Boss1{
    public Car getCar{
        Car car=new Car();
        car.setBrand("宝马z4");
        return car;
    }
}

public class Boss2 implements MethodPlacer{
    public Object reimplement(Object arg0,Method arg1,Object [] arg2) throws Throwable{
        Car car=new Car();
        car.setBrand("美人豹");
    }
}

"boss1" class="com.smart.simple.Boss1">
    "getCar" replacer="boss2"/>

"boss2" class="com.smart.simple.Boss2"/>

五、Bean之间的关系

5.1 继承

<bean id="abstractCar" class="com.smart.simple.Car" p:brand="红旗" p:price="2000" p:color="黑色" abstract="true"/>

<bean id="car1" p:color="白色" parent="abstract"/>

5.2 依赖

一般情况下,可以使用建立对其他bean的依赖关系。但在某些情况下,要保证依赖项在被依赖项提前初始化,可以使用显式指定bean前置依赖的bean。如果前置依赖于多个bean,可以通过逗号空格或分号等方式创建bean的明晨。

id="manager" class="com.smart.simple.Manager" depend-on="sysInt"/>
id="sysInt" class="com.smart.simple.SysInt"/>

5.3 引用

<bean id="car" class="com.smart.simple.Car"/>
<bean id="boss" class="com.smart.simple.Boss">
    <property name="carId">
        <idref bean="car"/>
    property>
bean>

六、 整合多个配置文件

spring允许通过将多个配置文件引入到一个文件中。
现假设有bean1.xml这个配置文件中有id=”car1”的bean,在bean2.xml中。

<import resource="classpath:com/smart/simple/bean1.xml"/>
"boss1" class="com.smart.simple.Boss" p:car-ref="car1"/>

七、 Bean作用域

7.1 singleton作用域

在默认情况下,Spring的ApplicationContext容器在启动时,自动实例化所有singleton的Bean并缓存到容器中。如果用户徐希望在容器启动时提前实例化singleton的bean,可以通过lazy-init属性进行控制。

"boss1" class="com.smart.simple.Boss" p:car-ref="car" lazy-init="true"/>

7.2 prototype作用域

采用scope=”prototype”指定非单例作用域的bean。默认情况下,spring容器在启动时不实例化prototype的Bean。此外,spring容器将prototype的Bean交给调用者后,就不再管理它的生命周期。

7.3 与web应用环境相关的bean作用域

需要进行的额外配置(在高版本的web容器中)

<listener>
    <listener-class>
    org.springframework.web.context.request.RequestContextListener
    listener-class>
listener>

7.3.1 request作用域
request作用域的bean对应一个Http请求的声明周期。每次http请求时会创建一个bean,请求处理完毕后,就销毁这个bean。

"car" class="com.smart.simple.Car" scope="request"/>

7.3.2 session作用域
session作用域横跨整个http session,session中的所用http请求都共享同一个bean,当http session结束后,实例才被销毁。

"car" class="com.smart.simple.Car" scope="session"/>

7.3.3 globalSession作用域
globalSession作用域类似于session作用域,不过尽在Portlet的web应用中使用。

"car" class="com.smart.simple.Car" scope="globalSession"/>

7.4 作用域依赖问题(略)

八、 FactoryBean

当实例化Bean的过程比较复杂,需要在中提供大量的配置信息,可以考虑采用编码方式实例化bean。

import org.springframework.beans.factory.FactoryBean;
import entity.Car;

public class CarFactoryBean implements FactoryBean{
    private String carInfo;

    public String getCarInfo() {
        return carInfo;
    }

    public void setCarInfo(String carInfo) {
        this.carInfo = carInfo;
    }

    @Override
    //采用逗号分割的属性设置信息
    public Car getObject() throws Exception {
        Car car=new Car();
        String[] infos=carInfo.split(",");
        car.setBrand(infos[0]);
        car.setColor(infos[1]);
        car.setMaxSpeed(Integer.parseInt(infos[2]));
        return car;
    }

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

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

"car10" class="chapter5.CarFactoryBean" p:carInfo="红旗CA72,红色,12000"/>

你可能感兴趣的:(spring)