基础篇——Spring之IOC容器装配Bean

1、Spring装配Bean的过程大致如下:

    Spring启动时读取应用程序提供的bean配置信息,并在Spring容器中生成一份该Bean的配置信息注册表,再根据该注册表实例化Bean,装配Bean的属性信息,Bean之间的依赖关系和Bean的行为配置。需要满足的三个条件:Spring框架的相关jar包(Spring容器)、Bean的配置信息、Bean的实现类。

2、bean配置信息的装载方式:XML的配置方式,基于注解的配置方式,基于Java类的配置方式,Groovy动态语言的配置方式。

3、XML配置方式之Schema配置大致包含两部分:一部分需要对用到的命名空间进行声明;另一部分则需要对声明的命名空间进行定义,定义包括命名空间名称和位置。

    命名空间的声明:通过xmlns:别名=“命名空间名称”的格式,如下:

 

//默认命名空间的声明
xmlns="http://www.springframework.org/schema/beans"
//标准命名空间的声明
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
//aop命名空间的声明
xmlns:aop="http://www.springframework.org/schema/aop"

     注:默认命名空间没有别名,常用标签<beans></beans>,<bean></bean>

     注:aop是自定义命名空间,常用标签<aop:config></aop:config>

    命名空间的定义:通过xsi:schemaLocation=“命名空间全称   schema文件位置”的格式,如下:

 

xsi:schemaLocation=
        "http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"

 4、XML配置方式之Spring常用的Schema文件:

    spring-beans-4.0.xsd:用于配置Bean;  spring-aop-4.0.xsd:用于AOP的配置;  spring-tx-4.0.xsd:用于声明式事务的配置;  spring-mvc-4.0.xsd:用于MVC的配置;  spring-util-4.0.xsd:用于简化某些标准配置;  spring-jee-4.0.xsd:用于简化JavaEE中EJB、JNDI等功能的配置;  spring-jdbc-4.0.xsd:用于Spring内嵌数据库的配置;  spring-jms-4.0.xsd:用于JMS的配置;  spring-lang-4.0.xsd:用于集成Groovy等动态语言;  spring-oxm-4.0.xsd:用于对象XML映射的配置;  spring-task-4.0.xsd:用于任务调度;  spring-tool-4.0.xsd:用于集成一些工具。

 5、XML配置方式之装配Bean,如下:

 

<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-4.0.xsd"> <bean id="car" class="com.smart.simple.Car"/> <bean name="boss" class="com.smart.simple.Boss"/> </beans>

     注:bean的命名可以用id或name,其中id被要求必须以字母开头且不能出现逗号、空格等非结束符号,name没有字符限制。

     注:bean可以指定多个名称,如下:

 

<bean id="car,car1,car2" calss="com.smart.simple.Car"/>
<bean name="boss1,boss2,boss3" calss="com.smart.simple.Boss">

 6、XML配置方式之属性注入,大致有三种注入方式:第一种属性注入,第二种构造函数注入,第三种工厂方法注入。

    属性注入是通过该属性的setter方法进行注入的方式,一般需要两个条件:一个是需要被注入对象有空参数的构造函数,另一个是需要被注入对象有该属性的setter方法设置值。Spring容器先调用空构造实例化被注入的bean,再调用其setter方法注入属性值,被注入对象示例如下:

 

package com.smart.ditype
public class Car{
    
    private String color;
    //被注入对象的空构造
    public Car(){}
    //被注入对象属性的setter方法
    public void setColor(String color){
        
        this.color = color;
  }
}

     注:如果类中没有定义任何构造函数,那么JVM会自动生成一个默认的空构造,上述Bean的配置文件如下:

 

<bean id="car" class="com.smart.ditype.Car">
    <property name="color" value="红色">
</bean>

7、XML配置方式之构造函数注入:

    构造函数注入是Bean在实例化时以参数的形式注入,大致有三种入参方式:根据类型入参、根据索引入参、类型和索引的联合、通过自身类型的反射入参。被注入对象的有参构造函数如下:

 

package com.smart.ditype
public class Car{

private String color;

private int maxSpeed; //被注入对象的有参构造
public Car(String color,int maxSpeed){

this.color = color;

this.maxSpeed = maxSpeed;
} }

    该对象Bean的配置文件如下:

 

<bean id="Car" class="com.smart.ditype.Car">
    <constructor-arg type="java.lang.String">
        <value>红色</value>
    </constructor-arg>
    <constructor-arg type="java.lang.Integer">
        <value>200</value>
     </constructor-arg>
</bean>

    注:在被注入对象的有参构造函数里,参数类型各不相同时,采用类型入参。若是有多个相同类型的参数,一般采取根据索引入参,其有参构造函数如下:

 

package com.smart.ditype
public class Car{

private String color;

private String type;
//被注入对象的有参构造 public Car(String color,String type){

this.color = color;

this.type = type;
} }
 

    该对象Bean的配置文件如下:

 

<bean id="car" class="com.smart.ditype.Car">
    <constructor-arg index="0" value="红色"/>
    <constructor-arg index="1" value="X-LL130"/>
</bean>

     注:在属性注入中Spring会通过属性名找到Bean对象中的setter方法设置属性,而在构造函数注入中Spring不能通过属性名找到构造函数的参数,需要通过类型或索引间接设置参数。若是重载多个参数个数相同的构造函数,被注入对象如下:

 

package com.smart.ditype
public Car{

    private String color;

    private String type;

private double price;
private int maxSpeed; //被注入对象的有参构造 public Car(String color,String type,int maxSpeed){ this.color = color;

this.type = type;
this.maxSpeed = maxSpeed; } //重载有参构造 public Car(String color,String type,double price){
this.color = color;
this.type = type; this.price = price; } }

    注:上述使用索引入参不能准确的注入到需要的构造函数中,需要在Bean对象的配置文件中联合使用类型入参和索引入参,如下:

 

<bean id="car" class="com.smart.ditype.Car">
    <constructor-arg index="0" value="红色"/>
    <constructor-arg index="1" value="x-ll123"/>
    <constructor-arg index="3" type="java.lang.Integer" value="200"/>
</bean>

    注:这样就能准确的将属性值注入到被注入对象的第一个有参构造中。但是使用有参构造函数注入方式可能出现循环依赖的问题,如下:

 

package com.smart.ditype
public class Car{
    
    private Boss boss;
    //被注入对象注入Bean
    public Car(Boss boss){

        this.boss = boss;
    }
}
package com.smart.ditype
public class Boss{
    
    private Car car;
    //被注入对象注入Bean
    public Boss(Car car){
    
        this.car = car;
    }
}

    bean的配置文件如下:

 

<bean id="car" class="com.smart.ditype.Car">
    <constructor-arg index="0" ref="boss"/>
</bean>
<bean id="boss" class="com.smart.ditype.Boss">
    <constructor-arg index="0" ref="car"/>
</bean>

    注:Spring容器通过构造函数实例化Bean,前提是Bean构造函数引入的参数必须是准备就绪的。当①对象需要注入一个Bean,注入方式采用的是构造函数注入,而这个Bean需要注入①对象,注入方式也采用的是构造函数注入,那么这两个bean都不能通过Spring容器进行实例化,这个问题就是循环依赖,类似于线程死锁的循环。

 

 

posted @ 2018-11-15 12:04  不浪小生  阅读(490)  评论(0编辑  收藏  举报